[comp.sys.amiga.tech] Amiga semaphores

jimg@hp-ptp.HP.COM (Jim_Garrison) (09/14/90)

Hello,

I've trying to use Amiga Semaphores, as a mechanism to let only one program
access a particular resource at a time.  I'm using the Amiga Programmers
Reference by Eugene Mortimer, as a reference for using the semaphores.  I
seem to recall that there is either some problem with the description of
semaphores in this book, or there are problems with the way Amiga semaphores
work.  I'm using an A2500 with Amigados 1.3 and Lattice 5.05 C compiler.

I've provided some code which seems like it should work, but doesn't.  If
two copies of this program are run at the same time, the first copy should
get the resource, and the second copy should wait until the first copy is
done.  Right now, FindSemaphore("test1") returns null in both programs, so
they both access the resource, and mess each other up.  Am I using
FindSemaphore() wrong, or am I using AddSemaphore() incorrectly?  I'd sure
appreciate any light shed on this.

Thanks in advance,


Jim Garrison (jimg@hpiatmh)
Hewlett Packard
Industrial Applications Center
(408) 746-5349


Sample program follows:


/* IPC.C - This is a test program, so I can see how Amiga semaphores work.
 *
 * 09/13/90 - Created by Jim Garrison.
 */

#include <stdio.h>
#include <libraries/dosextens.h>
#include <exec/semaphores.h>
#include <exec/memory.h>

main()
{
   struct SignalSemaphore *sem;
   int error;

   sem = FindSemaphore("test1");
   if (!sem)
   {
      sem = AllocMem(sizeof(struct SignalSemaphore), MEMF_PUBLIC | MEMF_CLEAR);
      printf("Making a semaphore\n");
      sem->ss_Link.ln_Name = "test1"; 
      sem->ss_Link.ln_Pri = 1; 
      error = AddSemaphore(sem);
      printf("Addsem error = %d\n", error);
   }
   else
      printf("Got an existing semaphore\n");
   ObtainSemaphore(sem);
   printf("Pausing ....\n");
   
/* Do something with some resource. */

   ReleaseSemaphore(sem);
   printf("Done\n");
   
}

jjszucs@cbmvax.commodore.com (John J. Szucs) (09/18/90)

In article <2290004@hp-ptp.HP.COM> jimg@hp-ptp.HP.COM (Jim_Garrison) writes:
>
>Hello,
>
>I've trying to use Amiga Semaphores, as a mechanism to let only one program
>access a particular resource at a time.  I'm using the Amiga Programmers
>Reference by Eugene Mortimer, as a reference for using the semaphores.  I
>seem to recall that there is either some problem with the description of
>semaphores in this book, or there are problems with the way Amiga semaphores
>work.  I'm using an A2500 with Amigados 1.3 and Lattice 5.05 C compiler.
>
[stuff deleted]
>
>Thanks in advance,
>
>
>Jim Garrison (jimg@hpiatmh)
>Hewlett Packard
>Industrial Applications Center
>(408) 746-5349
[code deleted]

Under Kickstart/Workbench Release 1.3, the exec.library/AddSemaphore function
does not work properly.

Use the following:

void LocalAddSemaphore(struct SignalSemaphore *SignalSemaphore)
{
	SignalSemaphore-.ss_Link.ln_Type=NT_SIGNALSEM;
	InitSemaphore(SignalSemaphore);
	Forbid();
	Enqueue(&SysBase->SemaphoreList,SignalSemaphore);
	Permit();
}

This is documented in the AutoDocs (available from CATS).

The function is correct under Kickstart/Workbench Release 2.0.

================================================================================
|| John J. Szucs                    || The opinions expressed are my own and  ||
|| Systems Evaluation Group         || in no way represent the opinions or    ||
|| Product Assurance Department     || policies of Commodore Technology, Inc. ||
|| Commodore Technology, Inc.       || or any associated entity.              ||
================================================================================
...{rutgers|uunet|pyramid}!cbmvax!jjszucs
jjszucs@cbmvax.commodore.com

"Everything is deeply intertwingled." - Ted Nelson, Computer Lib/Dream Machines

jimg@hp-ptp.HP.COM (Jim_Garrison) (09/18/90)

jjszucs@cbmvax.commodore.com (John J. Szucs) / 10:40 am  Sep 17, 1990 / writes:

>
>Under Kickstart/Workbench Release 1.3, the exec.library/AddSemaphore function
>does not work properly.

Aha! Great!  Thanks a bunch, now I can get back to work.  (Working a on a 
spooling program to print 2 pages per page on a LaserJet (or compatible)
printer.)

>
>Use the following:
>
>void LocalAddSemaphore(struct SignalSemaphore *SignalSemaphore)
>{
>	SignalSemaphore-.ss_Link.ln_Type=NT_SIGNALSEM;
>	InitSemaphore(SignalSemaphore);
>	Forbid();
>	Enqueue(&SysBase->SemaphoreList,SignalSemaphore);
>	Permit();
>}
>

Okay!

>This is documented in the AutoDocs (available from CATS).

Uh, where can I write to, so I can get these?  I'd sure like to get these
docs that relate to AmigaDOS 2.0 also.

>
>The function is correct under Kickstart/Workbench Release 2.0.
     ^^^^^^^^
AddSemaphore, I presume.  Now, if I can only get 2.0!



Thanks John, for your help, I appreciate being able to get this kind of support
over the net.


Regards,

Jim Garrison
Hewlett Packard

jjszucs@cbmvax.commodore.com (John J. Szucs) (09/20/90)

In article <2290005@hp-ptp.HP.COM> jimg@hp-ptp.HP.COM (Jim_Garrison) writes:
[referring to AutoDocs and other developer materials]
>Uh, where can I write to, so I can get these?  I'd sure like to get these
>docs that relate to AmigaDOS 2.0 also.

CATS is Commodore Applications and Technical Support (previously known as
Commodore-Amiga Technical Support).

The address is:

Commodore Business Machines, Inc.
CATS
1200 Wilson Drive
West Chester PA 19380

CATS can provide you with all the necessary information on availibility,
prices, etc.

>Thanks John, for your help, I appreciate being able to get this kind of support
>over the net.

I'm glad to help!

>Jim Garrison

================================================================================
|| John J. Szucs                    || The opinions expressed are my own and  ||
|| Systems Evaluation Group         || in no way represent the opinions or    ||
|| Product Assurance Department     || policies of Commodore Technology, Inc. ||
|| Commodore Technology, Inc.       || or any associated entity.              ||
================================================================================
...{rutgers|uunet|pyramid}!cbmvax!jjszucs
jjszucs@cbmvax.commodore.com

"Everything is deeply intertwingled." - Ted Nelson, Computer Lib/Dream Machines

valentin@cbmvax.commodore.com (Valentin Pepelea) (09/21/90)

In article <2290004@hp-ptp.HP.COM> jimg@hp-ptp.HP.COM (Jim_Garrison) writes:
>
> I've trying to use Amiga Semaphores, as a mechanism to let only one program
> access a particular resource at a time.  I'm using the Amiga Programmers
> Reference by Eugene Mortimer, as a reference for using the semaphores.  I
> seem to recall that there is either some problem with the description of
> semaphores in this book, or there are problems with the way Amiga semaphores
> work.  I'm using an A2500 with Amigados 1.3 and Lattice 5.05 C compiler.

The problem is with the semaphore calls. First of all, the AddSemaphore()
function expect a parameter in the wrong register. Take a look ROM Kernel
Reference Manual: Includes&Autodocs for a work-around. The blue-greenish
manual.

Valentin
-- 
The Goddess of democracy? "The tyrants     Name:    Valentin Pepelea
may distroy a statue,  but they cannot     Phone:   (215) 431-9327
kill a god."                               UseNet:  cbmvax!valentin@uunet.uu.net
             - Ancient Chinese Proverb     Claimer: I not Commodore spokesman be

jimg@hp-ptp.HP.COM (Jim_Garrison) (09/21/90)

Hello again,

I tried adding the LocalAddSemaphores() which John Suchs suggested to my
program.  It still doesn't work!  Please note that I am using NAMED semaphores
here, maybe that's what's causing my problems.  Even after I have run this
program once (or more) FindSemaphore(name) still returns NULL.  Do named
semaphores work?  Or am I still not initializing my named semaphore 
incorrectly?  What I want to happen is that if two of these programs are run
at one time, only one will get (Create) the semaphore and the other will wait
(sleep) until the first one calls ReleaseSemaphore(sem).  This way, I can 
queue up any number of copies of this program, and each one will wait it's
turn for the resource (the printer) which cannot be shared.

Thanks again,

Jim Garrison (jimg@hpiatmh)
Hewlett Packard
Industrial Applications Center
(408) 746-5349


PS - I have sent in for the ordering information, so I can get the autodocs.

Sample program follows:


/* IPC.C - This is a test program, so I can see how Amiga semaphores work.
 *
 * 09/13/90 - Created by Jim Garrison.
 * 09/18/90 - Added in LocalAddSemaphore() suggested by John Suchs.
 */

#include <stdio.h>
#include <libraries/dosextens.h>
#include <exec/execbase.h>
#include <exec/semaphores.h>
#include <exec/memory.h>

extern ExecBase *SysBase;
struct IntuitionBase *IB;

main()
{
   struct SignalSemaphore *sem;
   int error;

/* This next ALWAYS returns a NULL, no matter how many times I run this
 * program. */

   sem = FindSemaphore("test1");

   if (!sem)
   {
      /* I'm typing this in from memory, so this next line might not be right
       * but I am doing it correctly in the code on my Amiga at home. */

      if ((IB = OpenLibrary("intuition.library", LIBRARY_REV)) == NULL)
	 exit(1);

      sem = AllocMem(sizeof(struct SignalSemaphore), MEMF_PUBLIC | MEMF_CLEAR);
      printf("Making a semaphore\n");
      LocalAddSemaphore(sem, "test1");
   }
   else
      printf("Got an existing semaphore\n");
   ObtainSemaphore(sem);
   printf("Pausing ....\n");
   
/* Do something with some resource. */

   ReleaseSemaphore(sem);
   printf("Done\n");
   
}

void LocalAddSemaphore(struct SignalSemaphore *SignalSemaphore, char *name)
{
	SignalSemaphore->ss_Link.ln_Type=NT_SIGNALSEM;
        SignalSemaphore->ss_Link.ln_Name = name; 
        SignalSemaphore->ss_Link.ln_Pri = 1; 
	InitSemaphore(SignalSemaphore);
	Forbid();
	Enqueue(&SysBase->SemaphoreList,SignalSemaphore);
	Permit();
}

rosenber@ra.abo.fi (Robin Rosenberg INF) (09/23/90)

Clearly the documentation on AddSemaphore() is misleading. Set the
name and priority _after_ InitSemaphore(). You don't need to set the
type since InitSemahore() does that. So it becomes:

(Could this be added to introduction to comp.sys.amiga.tech since a lot of
people get bitten by AddSemaphore() )

void LocalAddSemaphore(struct SignalSemaphore *SignalSemaphore, char *name)
{
	InitSemaphore(SignalSemaphore);
        SignalSemaphore->ss_Link.ln_Name = name; 
        SignalSemaphore->ss_Link.ln_Pri = 1; 
	Forbid();
	Enqueue(&SysBase->SemaphoreList,SignalSemaphore);
	Permit();
}

griffith@eecs.cs.pdx.edu (Michael Griffith) (09/24/90)

jimg@hp-ptp.HP.COM (Jim_Garrison) writes:

>Hello again,

>I tried adding the LocalAddSemaphores() which John Suchs suggested to my
>program.  It still doesn't work!  Please note that I am using NAMED semaphores
>here, maybe that's what's causing my problems.  Even after I have run this
>program once (or more) FindSemaphore(name) still returns NULL.  Do named
>semaphores work?  Or am I still not initializing my named semaphore 
>incorrectly?  What I want to happen is that if two of these programs are run

>/* IPC.C - This is a test program, so I can see how Amiga semaphores work.
> *
> * 09/13/90 - Created by Jim Garrison.
> * 09/18/90 - Added in LocalAddSemaphore() suggested by John Suchs.
> */

>void LocalAddSemaphore(struct SignalSemaphore *SignalSemaphore, char *name)
>{
>	SignalSemaphore->ss_Link.ln_Type=NT_SIGNALSEM;
>        SignalSemaphore->ss_Link.ln_Name = name; 
>        SignalSemaphore->ss_Link.ln_Pri = 1; 
>	InitSemaphore(SignalSemaphore);
>	Forbid();
>	Enqueue(&SysBase->SemaphoreList,SignalSemaphore);
>	Permit();
>}

It seems to me that your problem is thus:

You are temporarily allocating space (for the duration of your program) for the
name string in your node, but rather than making a permanent copy you are just
setting the pointer ln_Name to point to it. Your program then terminates,
freeing the memory allocated for the string. Something else uses this memory,
overwriting your string and making it impossible for FindSemaphore to locate
it. Try the following inserted in place of the line where you set ln_Name:

   SignalSemaphore->ss_Link.ln_Name = AllocMem(sizeof(char)*(strlen(name)+1),
                                                MEMF_PUBLIC);
   strcpy(SignalSemaphore->ss_Link.ln_Name,name);

   /* I know this could be more elegant, and you should check to make sure
      the allocation is succesful, but since it's just a test... ;) */

Anyways, hope that helps.


| Michael Griffith                     | If I had an opinion it certainly   |
| griffith@eecs.ee.pdx.edu             | wouldn't be the same one as        |
| ...!tektronix!psueea!eecs!griffith   | Portland State University anyways. |

valentin@cbmvax.commodore.com (Valentin Pepelea) (09/25/90)

In article <2290006@hp-ptp.HP.COM> jimg@hp-ptp.HP.COM (Jim_Garrison) writes:
>
> I tried adding the LocalAddSemaphores() which John Suchs suggested to my
> program.  It still doesn't work!  Please note that I am using NAMED semaphores
> here, maybe that's what's causing my problems.  Even after I have run this
> program once (or more) FindSemaphore(name) still returns NULL.  Do named
> semaphores work?
> ...
> Sample program follows:
> ...
> LocalAddSemaphore(sem, "test1");

All right, here's what's happening. While you are allocating the semaphore
structure dynamically, the string "test1" is part of the program's global
variables. When the program exits, all variables disappear. Therefore when
you first run the program, the semaphore is indeed added properly to the
system.

But as soon as the program exits, the "test1" string is freed, and the memory
in which it resided is likely to be soon overwritten. Do an AllocMem() for the
name field of the semaphore, then copy the string in there. That will do it.

Valentin
-- 
The Goddess of democracy? "The tyrants     Name:    Valentin Pepelea
may distroy a statue,  but they cannot     Phone:   (215) 431-9327
kill a god."                               UseNet:  cbmvax!valentin@uunet.uu.net
             - Ancient Chinese Proverb     Claimer: I not Commodore spokesman be

jimg@hp-ptp.HP.COM (Jim_Garrison) (09/25/90)

Well, I did try InitSemaphore() before initializing the name and priority of
my semaphore.  I also made sure that I allocated (AllocMem'ed) some space for
the semaphore name.  IT STILL DOESN'T WORK!  Boy, I'd sure appreciate it if 
someone could mail me, or post some source code for named semaphores that
works (Especially the FindSemaphore() part.)  I even tried booting up as a
68000, instead of the 68030, to no avail.  Darn, and I thought this whole
thing with semaphores was going to take me a few minutes!

Thanks everyone for your replies and suggestions,

Jim Garrison
Hewlett Packard
(408) 746-5349

jimg@hp-ptp.HP.COM (Jim_Garrison) (09/26/90)

I just got some messages from another machine, that indicated someone has been
trying to mail me something related to this problem.  It appears that they're
trying to mail to me on the machine where I posted these notes from, but I
don't have a mail account on that machine.  If you are trying to mail me,
please try:

jimg@hpiatmh.hp.com

or just post it to notes, if it's not too big.


Thanks again,

Jim Garrison
Hewlett Packard
jimg@hpiatmh.hp.com
(408) 746-5349

jimg@hp-ptp.HP.COM (Jim_Garrison) (09/27/90)

Yahoo, thanks to Peter Xrbfk, I now have working Amiga semaphores.  I guess 
that my problem was that FindSemaphore() doesn't work either.  I have included
Peter's example program which works fine for me.  As someone else mentioned,
I think it might be a good idea to include this information in the Amiga 
introduction.

Thank you all for your help,

Jim Garrison
Hewlett Packard
jimg@hpiatmh
(408) 746-5349


>Hi, Jim.
>
>I suppose it was I who tried to post this to you at the wrong address.
>
>This works on my A500, ie. creates the semaphore once, and finds it 
>afterwards. It did not work with FindSemaphore() which seems to have
>a slight hitch in that it expects the name in A1 and not in A0 as indicated
>in the .fd file. One could consider this to be an error of the compiler
>makers who have not noticed this.
>
>With Aztec C 3.4 this program does the trick, but it shouldn't
>be compiler dependent.
>
>I hope this works for you too.
>
>
>  - Peter (poe@daimi.aau.dk)
>
---- cut here ----
/* sem.c */

/*
   Created 26-Sep-90 by Peter Xrbfk.
   This works on my A500 (KS 33.180 / WB 34.20)
*/

#include	"exec/types.h"
#include	"exec/semaphores.h"
#include	"exec/execbase.h"
#include	"exec/memory.h"
#include	"stdio.h"


struct Node *FindName();
void *AllocMem();
char *strcpy();

extern struct ExecBase *SysBase;

/*
   Define private version of FindSemaphore() because FindSemaphore()
   really expects the namepointer in A1 and not in A0 as indicated
   in the .fd files
*/

#define FindSem(s) (struct SignalSemaphore *)FindName(&SysBase->SemaphoreList,s)

main()
{
	struct SignalSemaphore *ss;
	char *str;

	if(!(ss = FindSem("MySem"))) {
		printf("didn't find semaphore\n");
		ss = (struct SignalSemaphore *)
			AllocMem((long)sizeof(struct SignalSemaphore),
				 MEMF_PUBLIC|MEMF_CLEAR);
		/* assume ok */
		InitSemaphore(ss);
		str = AllocMem(10L,MEMF_PUBLIC);
		ss->ss_Link.ln_Name = strcpy(str,"MySem");
		ss->ss_Link.ln_Pri = 0;

		printf("adding it\n");
		/* add it */
		Forbid();
		AddTail(&SysBase->SemaphoreList,ss);
		Permit();
		printf("semaphore created and added\n");
	}

	/* use it for something */
	ObtainSemaphore(ss);

	printf("bla\n");

	ReleaseSemaphore(ss);
}