home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / exec / releasesemaphore.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-09  |  4.2 KB  |  168 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: releasesemaphore.c,v 1.8 1997/01/01 03:46:14 ldp Exp $
  4.     $Log: releasesemaphore.c,v $
  5.     Revision 1.8  1997/01/01 03:46:14  ldp
  6.     Committed Amiga native (support) code
  7.  
  8.     Changed clib to proto
  9.  
  10.     Revision 1.7  1996/12/10 13:51:51  aros
  11.     Moved all #include's in the first column so makedepend can see it.
  12.  
  13.     Revision 1.6  1996/10/24 15:50:54  aros
  14.     Use the official AROS macros over the __AROS versions.
  15.  
  16.     Revision 1.5  1996/09/13 17:51:24  digulla
  17.     Use IPTR
  18.  
  19.     Revision 1.4  1996/08/13 13:56:05  digulla
  20.     Replaced AROS_LA by AROS_LHA
  21.     Replaced some AROS_LH*I by AROS_LH*
  22.     Sorted and added includes
  23.  
  24.     Revision 1.3  1996/08/01 17:41:16  digulla
  25.     Added standard header for all files
  26.  
  27.     Desc:
  28.     Lang: english
  29. */
  30. #include "exec_intern.h"
  31. #include "semaphores.h"
  32. #include <exec/semaphores.h>
  33. #include <proto/exec.h>
  34.  
  35. /*****************************************************************************
  36.  
  37.     NAME */
  38.  
  39.     AROS_LH1(void, ReleaseSemaphore,
  40.  
  41. /*  SYNOPSIS */
  42.     AROS_LHA(struct SignalSemaphore *, sigSem, A0),
  43.  
  44. /*  LOCATION */
  45.     struct ExecBase *, SysBase, 95, Exec)
  46.  
  47. /*  FUNCTION
  48.     Releases a lock on a semaphore obtained with either ObtainSemaphore(),
  49.     ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
  50.     Each call to one of those functions must be accompanied with one
  51.     call to ReleasSemaphore().
  52.  
  53.     INPUTS
  54.     sigSem - pointer to semaphore structure
  55.  
  56.     RESULT
  57.  
  58.     NOTES
  59.     This function preserves all registers.
  60.  
  61.     EXAMPLE
  62.  
  63.     BUGS
  64.  
  65.     SEE ALSO
  66.  
  67.     INTERNALS
  68.  
  69.     HISTORY
  70.     29-10-95    digulla automatically created from
  71.                 exec_lib.fd and clib/exec_protos.h
  72.     22-01-96    fleischer implementation
  73.  
  74. *****************************************************************************/
  75. {
  76.     AROS_LIBFUNC_INIT
  77.     AROS_LIBBASE_EXT_DECL(struct ExecBase *,SysBase)
  78.  
  79.     /* Arbitrate for the semaphore structure */
  80.     Forbid();
  81.  
  82.     /* Lower the use count. >0 means exclusive, <0 shared locked */
  83.     if(sigSem->ss_NestCount>0)
  84.     sigSem->ss_NestCount--;
  85.     else
  86.     sigSem->ss_NestCount++;
  87.  
  88.     /*
  89.     Now if the semaphore is free and there are other tasks waiting
  90.     wake them up.
  91.     */
  92.     if(!sigSem->ss_NestCount&&sigSem->ss_WaitQueue.mlh_Head->mln_Succ!=NULL)
  93.     {
  94.     /* Get first node in the waiting list */
  95.     struct SemaphoreNode *sn;
  96.     sn=(struct SemaphoreNode *)sigSem->ss_WaitQueue.mlh_Head;
  97.  
  98.     /* Is it a shared lock? */
  99.     if((IPTR)sn->node.ln_Name!=SM_EXCLUSIVE)
  100.     {
  101.         /* Yes. Process all shared locks in the list. */
  102.         while(sn->node.ln_Succ!=NULL)
  103.         {
  104.         /* Remember node */
  105.         struct SemaphoreNode *on=sn;
  106.  
  107.         /* Get next node now because there is a Remove() lurking */
  108.         sn=(struct SemaphoreNode *)sn->node.ln_Succ;
  109.  
  110.         /* Is this a shared lock? */
  111.         if((IPTR)on->node.ln_Name!=SM_EXCLUSIVE)
  112.         {
  113.             /* Yes. Remove it from the list */
  114.             Remove(&on->node);
  115.  
  116.             /* Wake the new owner. Check access type. */
  117.             if(on->node.ln_Pri==SN_TYPE_OBTAIN)
  118.             /* ObtainSemaphore() type. Send the semaphore signal. */
  119.             Signal(on->task,SEMAPHORESIGF);
  120.             else
  121.             {
  122.             /* Procure() type. Reply the semaphore message. */
  123.             ((struct SemaphoreMessage *)on)->ssm_Semaphore=sigSem;
  124.             ReplyMsg((struct Message *)on);
  125.             }
  126.  
  127.             /*
  128.             Mark the semaphore as having one more openers.
  129.             This happens here because the new owner(s) may need
  130.             some time to really wake up and I don't want other
  131.             tasks obtaining the semaphore before him.
  132.             */
  133.             sigSem->ss_NestCount--;
  134.         }
  135.         /* Dito. Invalidate the owner field. */
  136.         sigSem->ss_Owner=NULL;
  137.         }
  138.     }else
  139.     {
  140.         /* The new owner wants an exclusive lock. Remove him from the list. */
  141.         Remove(&sn->node);
  142.  
  143.         /* Check access type */
  144.         if(sn->node.ln_Pri==SN_TYPE_OBTAIN)
  145.         {
  146.         /*
  147.             ObtainSemaphore() type. Set the owner field and
  148.             Send the semaphore signal.
  149.         */
  150.         sigSem->ss_Owner=sn->task;
  151.         Signal(sn->task,SEMAPHORESIGF);
  152.         }else
  153.         {
  154.         /* Procure() type. Reply the message. */
  155.         ((struct SemaphoreMessage *)sn)->ssm_Semaphore=sigSem;
  156.         sigSem->ss_Owner=((struct Message *)sn)->mn_ReplyPort->mp_SigTask;
  157.         ReplyMsg((struct Message *)sn);
  158.         }
  159.         /* Mark the semaphore as having one more openers. */
  160.         sigSem->ss_NestCount++;
  161.     }
  162.     }
  163.  
  164.     /* All done. */
  165.     Permit();
  166.     AROS_LIBFUNC_EXIT
  167. } /* ReleaseSemaphore */
  168.