TLIMONCE@DREW.BITNET (05/27/88)
I have a question about Semaphores. I have used Semaphores on other systems but I can't figure out how to do them on the Amiga. I'm sure this would be of public interest so if someone could just post a quick summery of how to allocated them, UP() and DOWN() them, and destroy them. (or anything else I should know). I have the 1.2 Autodocs... but I must not have my eyes on straight when I read them because I can't figure it out. Someone told me they are implemented "like messages". Well, I have programs talking to other programs with no problem using regular message ports, etc. Thanks in advance! Tom A // Tom Limoncelli -- TLimonce@Drew.Bitnet \ M // "Never trust a person that doesn't know machine language!" \ I \\// /\ G XX "Have you hugged your SO today?" / \ A -------------------------------------------------------------------------- "The above are my views, not those of Drew University or my employer"
carolyn@cbmvax.UUCP (Carolyn Scheppner CATS) (06/08/88)
In article <8805271342.AA13064@jade.berkeley.edu> TLIMONCE@DREW.BITNET writes: >I have a question about Semaphores. >... Check comp.sources.amiga for Phil Lindsay's Semaphore.c. If it's not there, mail me and I will send it to the sources group. -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Carolyn Scheppner -- CATS >>Commodore Amiga Technical Support<< UUCP ...{allegra,ihnp4,rutgers}!cbmvax!carolyn PHONE 215-431-9180 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
d5adria@dtek.chalmers.se. (Martin Adrian) (11/20/89)
I can't get the function AddSemaphore to work.
My program looks like this:
main()
{
struct SignalSemaphore ss;
/* set name and pri */
AddSemaphore(&ss);
....
RemSemaphore(&ss);
}
The guru will show up every time with different nubers.
When i disassembled the exec function AddSemaphore it looked like this(Ks1.3):
AddSemaphore: JSR _LVOInitSemaphore(A6)
LEA SemaphoreList+LH_Head(A6),A0
BRA xxxx ;do Enqueue
When i looked up the functions in programmers guide i found that AddSemaphore
wants the Semaphorepointer in A1 and InitSemaphore in A0.
(The lattice proto/exec.h was wrong about this)
InitSemaphore also destroys A0,A1,D0,D1.
As far as i can see there is no way that this function can work.
BTW this macro works fine.
#define AddSemaphore(ss) InitSemaphore(ss),\
Enqueue(ExecBase->SemaphoreList,&(ss)->ss_Link)
^
the semaphore node
Is this a known bug in Exec ?
Martin Adrian.
haeb@ibmpcug.co.uk (Harry Broomhall) (11/25/89)
In article <1716@mathrt0.math.chalmers.se> d5adria@dtek.chalmers.se (Martin Adrian) writes: > I can't get the function AddSemaphore to work. > > My program looks like this: > (stuff deleted, but basicaly a simple call to AddSemaphore) > > When i looked up the functions in programmers guide i found that AddSemaphore > wants the Semaphorepointer in A1 and InitSemaphore in A0. > (The lattice proto/exec.h was wrong about this) > > Is this a known bug in Exec ? > > Martin Adrian. yes - this is documented in the latest edition of RKM, and a work-around is given: void AddSemaphore(s) struct SignalSemaphore *s; { InitSemaphore(s); Forbid(); Enqueue(&SysBase->SemaphoreList, s); Permit(); } Note the use of the Forbid(), Permit() pair when playing with system lists! On another note, Lattice C V5.02 has further faults in proto/exec.h The 'magic' numbers given for RemSemaphore and FindSemaphore are wrong. They imply that the semaphore is passed in A0, whem in fact it is in A1. Alter the numbers from 801 to 901 and all should work. Regards, Harry Broomhall. -- Automatic Disclaimer: The views expressed above are those of the author alone and may not represent the views of the IBM PC User Group.
mks@cbmvax.UUCP (Michael Sinz - CATS) (12/02/89)
In article <1716@mathrt0.math.chalmers.se> d5adria@dtek.chalmers.se (Martin Adrian) writes: >I can't get the function AddSemaphore to work. > >My program looks like this: > >main() >{ > struct SignalSemaphore ss; > > /* set name and pri */ > > AddSemaphore(&ss); Note that AddSemaphore is Broken in the 1.2/1.3 ROMs and you must use the work-around published in AmigaMail and in the AutoDocs and in the RKM: Includes & AutoDocs... (Blue cover...) > > .... > > RemSemaphore(&ss); >} > >The guru will show up every time with different nubers. > >When i disassembled the exec function AddSemaphore it looked like this(Ks1.3): >AddSemaphore: JSR _LVOInitSemaphore(A6) > LEA SemaphoreList+LH_Head(A6),A0 > BRA xxxx ;do Enqueue > >When i looked up the functions in programmers guide i found that AddSemaphore >wants the Semaphorepointer in A1 and InitSemaphore in A0. >(The lattice proto/exec.h was wrong about this) > >InitSemaphore also destroys A0,A1,D0,D1. > >As far as i can see there is no way that this function can work. > > BTW this macro works fine. >#define AddSemaphore(ss) InitSemaphore(ss),\ > Enqueue(ExecBase->SemaphoreList,&(ss)->ss_Link) > ^ > the semaphore node Note that you need to do the following: InitSemaphore(ss); Forbid(); Enqueue(ExecBase->SemaphoreList,ss); Permit(); You MUST Forbid()/Permit() >Is this a known bug in Exec ? > >Martin Adrian. /----------------------------------------------------------------------\ | /// Michael Sinz -- CATS/Amiga Software Engineer | | /// PHONE 215-431-9422 UUCP ( uunet | rutgers ) !cbmvax!mks | | /// | |\\\/// When people are free to do as they please, | | \XX/ they usually imitate each other. | \----------------------------------------------------------------------/
caw@miroc.UUCP (Christopher A. Wichura) (02/03/90)
I am about to start fooling with semaphores for a program I am working on and have run across something that bothers me. There is no opposite to InitSemaphore() that I can find. When my program wants to exit, which includes closing down the semaphore, what do I do? Is it `safe' to simply drop the semaphore if all ObtainSemaphore()s have been matched by an equal number of ReleaseSemaphore()s? This will be a private semaphore so I don't have to worry about removing it from the system lists, or at least so it would seem. -=> CAW -- /////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Christopher A. Wichura ...!jolnet!miroc!caw (my amiga) u12401@uicvm.uic.edu (my school account) \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//////////////////////////////////////
mks@cbmvax.commodore.com (Michael Sinz - CATS) (02/12/90)
In article <00253.AA00253@miroc> caw@miroc.UUCP (Christopher A. Wichura) writes: >I am about to start fooling with semaphores for a program I am working on >and have run across something that bothers me. There is no opposite to >InitSemaphore() that I can find. When my program wants to exit, which >includes closing down the semaphore, what do I do? Is it `safe' to simply >drop the semaphore if all ObtainSemaphore()s have been matched by an equal >number of ReleaseSemaphore()s? This will be a private semaphore so I don't >have to worry about removing it from the system lists, or at least so it >would seem. If the Semaphore is truly PRIVATE then when all users of the semaphore quit, the semaphore memory can just be FreeMem()ed. The semaphore contains only pointers to waiting tasks. If the semaphore was public, other work would need to be done. (Note that this is for SignalSemaphores...) > >-=> CAW >-- >-- /----------------------------------------------------------------------\ | /// Michael Sinz -- CATS/Amiga Software Engineer | | /// PHONE 215-431-9422 UUCP ( uunet | rutgers ) !cbmvax!mks | | /// | |\\\/// "I don't think so," said Ren'e Descartes. | | \XX/ Just then, he vanished. | \----------------------------------------------------------------------/
ccplumb@lion.waterloo.edu (Colin Plumb) (02/13/90)
In article <00253.AA00253@miroc> caw@miroc.UUCP (Christopher A. Wichura) writes: > I am about to start fooling with semaphores for a program I am working on > and have run across something that bothers me. There is no opposite to > InitSemaphore() that I can find. When my program wants to exit, which > includes closing down the semaphore, what do I do? Is it `safe' to simply > drop the semaphore if all ObtainSemaphore()s have been matched by an equal > number of ReleaseSemaphore()s? This will be a private semaphore so I don't > have to worry about removing it from the system lists, or at least so it > would seem. It is safe. A semaphore is just a private data structure manipulated by Exec which you have to allocate. Exec only manipulates it on an explicit call from you, so as long as no processes are dangling off it (which would result in unrecoverable resources, as the processes would never run and exit), if you can guarantee that nobody will ever again pass the semaphore to one of the Exec routines (which is true in your case), you can deallocate it like any other piece of memory. InitSemaphore() just sets up the data structure to the right value; there is no corresponding need to clear memory before deallocating it. -- -Colin
arc@desire.wright.edu (06/30/90)
There is a utility called Stat in the v2.0 of the Kramden utilities. It has a way to let you list all the semaphores in your system. There are only 2 programs that I've seen that use there own semaphore and these are Tracksalve and some other program (I forget it;s's name). How come more people don't use semaphrores? Wouldn't they help out a lot in some areas? I know that semaphorses in a Vax is useful for synchronizing tasks... Is this what they are used for on the Amiga? Would someone PLEASE elaborate? /Bryan ------------------------------------------------------------------------ = // | Bryan K. Fite | Arc@Desire.Wright.edu = = // Amiga! | ^Service Engineer^ | -or- = = \\// The One | Arc Electronics, Inc. | Arc@WSU.BITNET = = \/ & Only... | Wright State University | = = | Dayton, Ohio | Depeche' Mode, Now! = ========================================================================
Sullivan@cup.portal.com (sullivan - segall) (07/01/90)
> > There is a utility called Stat in the v2.0 of the Kramden utilities. >It has a way to let you list all the semaphores in your system. There >are only 2 programs that I've seen that use there own semaphore and these >are Tracksalve and some other program (I forget it;s's name). How come >more people don't use semaphrores? Wouldn't they help out a lot in some >areas? I know that semaphorses in a Vax is useful for synchronizing tasks... >Is this what they are used for on the Amiga? Would someone PLEASE elaborate? > The Amiga tends to use Forbid() and Permit() to serve this purpose. The good side of this is that you don't have to know what the name of the semaphore you want to allocate is. (Sorry about the verb, I've been studying German for too long.) The bad side is that you basically have the equivalent of one system semaphore for every program. As a result every task is blocked from running when you really only need to block programs requesting the same resource. Of course in many areas semaphore like operations are handled well. Filelocks, and library locks are examples. Some misbehaved programs can cause quite a bit of trouble though by abusing these semaphores. -kls
limonce@pilot.njin.net (Tom Limoncelli) (07/01/90)
In article <31309@cup.portal.com> Sullivan@cup.portal.com (sullivan - segall) writes: > Someone asks: > > Why don't people use the Amiga semaphore routines more often? > The Amiga tends to use Forbid() and Permit() to serve this purpose. The > good side of this is that you don't have to know what the name of the > semaphore you want to allocate is. (Sorry about the verb, I've been studying I think you missed two other reasons. First of all, the routines have bugs in them and if you don't have the work-around you might will get discouraged and stop using them. Secondly, if you do read the RKM section on semaphores you'll notice that it explains how to use them, but then says something like "Deadlocks can still occur if you're not careful, find a good book on operating systems (like the Minix book) for more info." Most people without a BA or BS in CS are going to read that and start using Forbid() and Permit(). (Soapbox) This must be a bad week for me because I've come across 3 cases where a software development problem "happened" because the programmers didn't have a good base in xxxx theory. (where xxxx = relational calculus (i.e. database), semaphore and disk scheduling) (Joke mode) Well I only have to take 1 CS class in my last year (next year) of college. I'll try to ignore the theory so I can "fit in" when I get to the job market. -Tom -- tlimonce@drew.edu Tom Limoncelli tlimonce@drew.uucp +1 201 408 5389 tlimonce@drew.Bitnet limonce@pilot.njin.net
brian@babbage.csus.edu (Brian Witt) (07/02/90)
In article <709.268c893f@desire.wright.edu> arc@desire.wright.edu writes: > There >are only 2 programs that I've seen that use there own semaphore and these >are Tracksalve and some other program (I forget it;s's name). How come >more people don't use semaphrores? Wouldn't they help out a lot in some >areas? I know that semaphorses in a Vax is useful for synchronizing tasks... >Is this what they are used for on the Amiga? Would someone PLEASE elaborate? OK, SimCity on the Amiga uses semaphores. When the Maps and Graphs screen needs updating it lokks the simulators database, redraws the map, then unlocks (V operation). Great way to provide consistant results!! :-) The application is user-time (ie, slow realtime), so someone can wait if they need to without damaging results. The critical section was entered only ocassionally (about once every 15 seconds). The lesson from the experience is: make the "locking mechanism" as "light" as possible. Perhaps code like: while(in_use) Delya(50L); would work just as well (ignoring race conditions). Kids, don't do this at home. (Please don't flame this paragraph. OK?) Since the code was developed simutaneously for the Amiga and the Macintosh, it was hard to get Amiga specific code in the simulator that ran in the background. In this case, it was more a problem of code clutter than actual programmer ignorance. BTW, to however wrote the Signal Semaphore package (I think Neil Katin): very cute, very sneaky, very clever solution; I like it! :-) :-) :-) > /Bryan --- Laws seldom stop polititicans --- brian witt uunet.uu.net!seer.UUCP!rael!aleks
limonce@pilot.njin.net (Tom Limoncelli) (07/03/90)
People have asked me to post the docs I have on semaphores. I found this in a very old directory on my hard drive. I can't find a source, but I'm sure it was posted to Usenet. One of the files mentions that the author got help from the people at C-A, so I assume it was written by someone that isn't a C-A Employee. -Tom Here it is: >>>>>>>>>>sem.doc<<<<<<<<<< I've been looking through the Autodocs on message & signal semaphores and I find them to be a little bit lacking (I know, this has been mentioned before). So I was hoping that I might clarify the use of them just a bit. These programs demonstrate what I think is going on, I invite you all to try to find problems with them... They seem OK to me but semaphores in any O/S are a really touchy area. ---- Message based semaphores (usually refered to as just 'Semaphores') make use of the Message sending/receiving/waiting protocols. In order to use them you must initialize a 'struct Semaphore' if you examine just what a struct Semaphore is you'll see that it is defined as struct Semaphore { struct MsgPort sm_MsgPort; WORD sm_Bids; } (it's in <exec/semaphores.h> like all of the semaphore definitions). To initialize it, you must allocate the memory for the structure and then do all of the usual MsgPort initialization things. Normally CreatePort() does all of this for you but you can't use it as you have do to a slightly different initialization for a semaphore. See the CreateSemaphore() function in the msgsem example. You can make a semaphore public by making its MsgPort public (i.e. giving the MsgPort a name & priority and using AddPort() to add the port to the system list of named ports). You can then find such a semaphore by using the FindPort() call... To remove the semaphore from the system you have do remove it from the public port list using RemPort() (iff you added it to that list) and then simply free the memory allocated for the structure. Assuming you have created the Semaphore, to use it you must allocate a message (to be used as your 'bid' for the semaphore) and port that this message will be sent to. Initialize the mn_ReplyPort field of your message to point to your port. You then use these two functions to lock/unlock the semaphore. Procure(Semaphore, BidMessage) struct Semaphore *Semaphore; struct Message *BidMessage; Procure() returns true if the semaphore can be locked for your use immediately. If the semaphore cannot be locked, your bid is queued up and when it becomes free your BidMessage will be sent the the port you allocated (the one that nm_ReplyPort in the BidMessage is supposed to point to). So if you need to get the Semaphore and you can't go on any further without it you must do something like if (!Procure(semaphore,message)) { WaitPort(message->mn_ReplyPort); GetMsg(message->nm_ReplyPort); } ... put code that needs the semaphore here ... This assumes that there is only one semaphore using this port for it's replies. Otherwise you have to be more complicated. Vacate(Semaphore) struct Semaphore *Semaphore; Vacate() unlocks the semaphore so that some other Procure() will succeed or if there is an outstanding bid then the bid message will sent to the appropriate port. So much for straight Semaphores. Now onto SignalSemaphores. ---- SignalSemaphores seem much easier to use on the surface only they are slightly broken which makes up for this. The AddSemaphore(), RemSemaphore() and FindSemaphore() calls all need special attention as they don't work as advertised in the Autodocs. Other than this difficulty, signal semaphores are very easy to deal with as there are no painful initialization rituals to remember as with message semaphores above... just allocate enough memory for the SignalSemaphore and you're off to the races. InitSemaphore(SignalSemaphore) struct SignalSemaphore *SignalSemaphore; Initializes a signal semaphore structure. Use this function for "private" semaphores (i.e. known only to tasks that have easy access to the creator's memory). AddSemaphore(SignalSemaphore) struct SignalSemaphore *SignalSemaphore; Adds the semaphore to the system list of semaphores. You must fill in the ss_Link.ln_{Type,Name,Pri} fields before calling this. AddSemaphore() calls InitSemaphore() so you don't need to do call this yourself if you use AddSemaphore(). N.B. The Exec version of this function seems to be broken. Use Dale's "hand crafted" version instead. (it's just a InitSemaphore() call followed by an atomic Enqueue on the system signal semaphore list). See example. RemSemaphore(SignalSemaphore) struct SignalSemaphore *SignalSemaphore; Removes the given semaphore from the system list of public semaphores. N.B. The amiga.lib and c[32].lib bindings for this function are broken. You must include your own bindings for this to work. See example. struct SignalSemaphore *FindSemaphore(name) char *name; Search the system list for semaphores for one with the given name. Returns a pointer to the semaphore if one is found, NULL otherwise. N.B. The amiga.lib and c[32].lib bindings for this function are broken. You must include your own bindings for this to work. See example. ObtainSemaphore(SignalSemaphore) struct SignalSemaphore *SignalSemaphore; This function locks the given semaphore for your use. If the semaphore is currently in use by someone else it blocks until it is Release'd by the current owner. A nesting count is maintained if you try to Obtain a semaphore that you already have. ReleaseSemaphore(SignalSemaphore) struct SignalSemaphore *SignalSemaphore; This function frees the given semaphore for use by someone else. If you Obtained the semaphore more than once the the nesting count is simply decremented rather than actually Releasing the semaphore. Bad things happen if you Release more times than you Obtain. AttemptSemaphore(SignalSemaphore) struct SignalSemaphore *SignalSemaphore; This function tries to Obtain the semaphore provided. If this can be done it locks the semaphore and returns true. If the semaphore is currently in use by someone else it returns false. Use this function if you don't want to block your task waiting for a semaphore. ObtainSemaphoreList(SemaphoreList) struct SemaphoreList *SemaphoreList; ReleaseSemaphoreList(SemaphoreList) struct SemaphoreList *SemaphoreList; Haven't played with these two yet... They're used for locking several semaphores in one atomic action. This ability can be used to prevent deadlock. ---- Note: The Kernel doesn't seem to do any kind of deadlock prevention or recovery. This means you have to decide for yourself if deadlock is an issue in your application. There are several good books which deal with deadlock avoidance and so forth so I won't go into that here. >>>>>>>>>>Makefile<<<<<<<<<< CFLAGS= +L all: msgsem sigsem msgsem: msgsem.o ln -o msgsem msgsem.o -lc32 sigsem: sigsem.o ln -o sigsem sigsem.o -lc32 >>>>>>>>>>msgsem.c<<<<<<<<<< #include <exec/types.h> #include <exec/nodes.h> #include <exec/ports.h> #include <exec/semaphores.h> #include <exec/memory.h> struct MsgPort *CreatePort(); struct MsgPort *FindPort(); struct XSemaphore *CreateSemaphore(); void DeleteSemaphore(); void *AllocMem(); void cleanup(); struct XSemaphore { struct Semaphore s; WORD Users; }; struct MsgPort *port = 0; struct XSemaphore *sem = 0; struct Message msg; /* I made this extended semaphore so that there is an easy way to * keep track of when it is safe to delete it. If anyone can think * of a better way to do this, I'd love to hear it. */ extern int Enable_Abort; main() { int i; Enable_Abort = 0; /* the existance check/creation must be atomic --> Forbid/Permit */ Forbid(); if (!(sem = (struct XSemaphore *)FindPort("my semaphore"))) sem = CreateSemaphore("my semaphore", 0); else sem->Users++; Permit(); if (!sem) { printf("Error, can't find *or* create semaphore\n"); cleanup(); exit(100); } port = CreatePort(0,0); if (!port) { printf("Error, can't create my reply port\n"); cleanup(); } msg.mn_Node.ln_Type = NT_MESSAGE; msg.mn_Length = sizeof(struct Message); msg.mn_ReplyPort = port; /* for P & V fans, the Procure & Vacate names are mnemonic */ /* - - */ for (i=0;i<5;i++) { if (!Procure(sem, &msg)) { WaitPort(port); /* wait for the message to come */ GetMsg(port); /* get it */ } /* we now have exclusive access */ printf("\nTask $%06x owns the semaphore\n",FindTask(0)); /* pretend to so some action requiring semaphore */ Delay(1 + (rand()&31)); printf("\t\t...semaphore now released\n"); /* yield control to someone else */ Vacate(sem); /* pretend to so some action not requiring semaphore */ Delay(1 + (rand()&31)); } cleanup(); } void cleanup() { if (port) { DeletePort(port); port = 0; } /* * we'd like to use the semaphore to lock out other users here * but we'd have to somehow P and then not do a V but delete * the port instead for this to work... That hurts me more than * the Forbid() Permit() pair... */ if (sem) { /* the user check/delete must be atomic --> Forbid/Permit */ Forbid(); if (--sem->Users == 0) DeleteSemaphore(sem); Permit(); sem = 0; } } struct XSemaphore *CreateSemaphore(name,pri) char *name; int pri; { struct XSemaphore *s; char *buf; s = AllocMem(sizeof(struct XSemaphore), MEMF_PUBLIC|MEMF_CLEAR); if (!s) return(0); s->s.sm_Bids = -1; NewList(&s->s.sm_MsgPort.mp_MsgList); s->s.sm_MsgPort.mp_Flags = PA_IGNORE; s->s.sm_MsgPort.mp_Node.ln_Type = NT_SEMAPHORE; s->s.sm_MsgPort.mp_Node.ln_Pri = pri; s->Users = 1; /* Note that the name must be copied as the original creator * of the semaphore might exit. We can't leave a pointer to * the original data segment lying around after the program * has exited. */ if (name) { buf = AllocMem(strlen(name)+1, MEMF_PUBLIC); if (!buf) { FreeMem(s, sizeof(struct XSemaphore)); return(0); } strcpy(buf,name); s->s.sm_MsgPort.mp_Node.ln_Name = buf; AddPort(s); } return(s); } void DeleteSemaphore(s) struct XSemaphore *s; { char *name; if (!s) return; name = s->s.sm_MsgPort.mp_Node.ln_Name; if (name) { RemPort(s); /* remove from list of public semaphores */ FreeMem(name,strlen(name)+1); } FreeMem(s, sizeof(struct XSemaphore)); } >>>>>>>>>>sigsem.c<<<<<<<<<< /* * This program plays around with signal semaphores... * * Thanks to C-A for providing the new bindings & AddSemaphore code * */< #include <exec/types.h> #include <exec/nodes.h> #include <exec/ports.h> #include <exec/semaphores.h> #include <exec/memory.h> #include <exec/execbase.h> struct XSSemaphore { struct SignalSemaphore s; WORD Users; }; void *AllocMem(); void cleanup(); void DeleteSSemaphore(); struct SignalSemaphore *myFindSemaphore(); struct XSSemaphore *CreateSSemaphore(); struct XSSemaphore *sem = 0; /* I made this extended semaphore so that there is an easy way to * keep track of when it is safe to delete it. If anyone can think * of a better way to do this, I'd love to hear it. */ extern int Enable_Abort; main() { int i; Enable_Abort = 0; /* the existance check/creation must be atomic --> Forbid/Permit */ Forbid(); if (!(sem = (struct XSSemaphore *)myFindSemaphore("sigSemaphore"))) sem = CreateSSemaphore("sigSemaphore",0); else sem->Users++; Permit(); if (!sem) { printf("Error, can't find *or* create semaphore\n"); cleanup(); exit(100); } for (i=0;i<5;i++) { /* get use of the semaphore */ ObtainSemaphore(sem); /* we now have exclusive access */ printf("\nTask $%06x owns the semaphore\n",FindTask(0)); /* pretend to so some action requiring semaphore */ Delay(1 + (rand()&31)); printf("\t\t...semaphore now released\n"); /* yield control to someone else */ ReleaseSemaphore(sem); /* pretend to so some action not requiring semaphore */ Delay(1 + (rand()&31)); } cleanup(); } void cleanup() { if (sem) { /* the user check/delete must be atomic --> Forbid/Permit */ Forbid(); if (--sem->Users == 0) DeleteSSemaphore(sem); Permit(); sem = 0; } } struct XSSemaphore *CreateSSemaphore(name,pri) char *name; int pri; { struct XSSemaphore *sem; char *buf; sem = AllocMem(sizeof(struct XSSemaphore), MEMF_PUBLIC|MEMF_CLEAR); if (!sem) return(0); sem->s.ss_Link.ln_Type = NT_SIGNALSEM; sem->s.ss_Link.ln_Pri = pri; /* Note that the name must be copied as the original creator * of the semaphore might exit. We can't leave a pointer to * the original data segment lying around after the program * has exited. */ if (name) { buf = AllocMem(strlen(name)+1, MEMF_PUBLIC); if (!buf) { FreeMem(sem, sizeof(struct XSSemaphore)); return(0); } strcpy(buf,name); sem->s.ss_Link.ln_Name = buf; myAddSemaphore(sem); } else InitSemaphore(sem); sem->Users = 1; return(sem); } void DeleteSSemaphore(sem) struct XSSemaphore *sem; { char *name; if (!sem) return; name = sem->s.ss_Link.ln_Name; if (name) { myRemSemaphore(sem); FreeMem(name, strlen(name) + 1 ); } FreeMem(sem, sizeof(struct XSSemaphore)); } /* The bindings for "AddSemaphore" are broken in 1.2 Amiga.lib * * Dale's handcrafted AddSemaphore(). */ myAddSemaphore(ss) struct SignalSemaphore *ss; { extern struct ExecBase *SysBase; InitSemaphore(ss); Forbid(); Enqueue(&SysBase->SemaphoreList,ss); Permit(); } /* The "C" interface code for the following semaphore routines is broken in * Amiga.lib and in the Aztec C release 3.4a. * * @ Lattice people should cut and paste the assembler into a separate file. */ #if AZTEC_C #asm ; The exec.library function "AddSemaphore" is broken in KickStart rel. 33.180 ; ; The Aztec bindings think that they should be using a0 to pass the ; argument instead of a1. This is likely the problem with the Lattice ; bindings. The Exec AddSemaphore function seems to be just plain broken. ; ; -Rico XREF _SysBase XREF _LVOFindSemaphore XREF _LVORemSemaphore XDEF _myFindSemaphore XDEF _myRemSemaphore _myFindSemaphore: move.l 4(sp),a1 move.l _SysBase,a6 jmp _LVOFindSemaphore(a6) _myRemSemaphore: move.l 4(sp),a1 move.l _SysBase,a6 jmp _LVORemSemaphore(a6) #endasm #endif -- tlimonce@drew.edu Tom Limoncelli tlimonce@drew.uucp +1 201 408 5389 tlimonce@drew.Bitnet limonce@pilot.njin.net