[comp.os.minix] Semaphores

merusi@pwa-b.UUCP (Don Merusi) (05/05/88)

I could probably find this out if I read THE BOOK, however, I thought
I'd ask the MINIX user community. Is there any semaphore capablity
presently in MINIX? By semaphore, I mean the P(S) V(S) Dijkstra style
synchronization flags. I would appreciate hearing from anybody about
this, or even if someone has plans for adding this capability if doesn't
already exist. Thanx.

cassidy@silver (Patrick Cassidy) (06/02/88)

              This is in response to the postings a couple of weeks ago 
         concerning semaphores.  I have added semaphores to Minix, but have 
         not been able to throughly test them yet.  The implementation of 
         semaphores consists of 3 new memory manager system calls:  
         makesem, psem, and vsem. Makesem takes the initial semaphore value 
         as an argument, and returns an integer value which identifies the 
         new semaphore.  That returned value is then used in subsequent 
         calls to psem and vsem, much like using a file descriptor.  When 
         it is necessary to block a process doing a wait (psem), that is 
         accomplished by simply not replying to the incoming message -- as 
         is done in the Pause system call. My plan for testing involves a 
         producer/consumer type situation.  As far as I can see, the 
         producer/consumer problem requires shared memory.  Judging from my 
         experience, implementing shared memory is MUCH harder than 
         implementing semaphores themselves. 
              Can anyone suggest a way to test semaphores in Minix that 
         doesn't require shared memory?
              In the mean time, here is what my approach to shared memory 
         involves:
              1)  Adding user-to-user message passing to Minix. 
                  This is necessary to enable the process which contains 
                  the shared data structure to send a pointer to that data 
                  structure to the other sharing process(s). 
              2)  Adding a system task system call so the memory manager can
                  access umap in the kernel.
              3)  Adding a memory manager system call so user processes can 
                  access umap through the memory manager.
              These three steps have been accomplished, including the 
         addition of library routines for the new system calls.  Here's how 
         it works in a nutshell:  First, the process containing the data 
         structure sends a message to the other sharing process(s) 
         containing a pointer to the data structure.  The receiver of this 
         message also needs the sender's pid and the length of the data 
         structure, but that info can just be inherited from a fork.  Next, 
         the second process makes the new system call (#3 above) using the 
         parameters just described.  At this point the second process has 
         the value returned by the kernel function umap, (the foreign 
         pointer has been unmapped).  Having this value, the second process 
         can read and write the data structure (in the first processes' 
         address space).
              I have been using the Minix function get_byte to accomplish 
         the reading.  I haven't gotten the writing to work yet -- because 
         there isn't an analogus function "put_byte" in Minix, and I don't 
         have a good assembly language reference.
              Although it isn't well tested, I believe my semaphore code (3 
         new memory manager system calls) is essentially correct.  If 
         anyone wants the code, respond to this posting or send me mail.  
         Also, if anyone out there has a put_byte function which takes the 
         same type of arguments as get_byte in Minix (segment, offset), I 
         would appreciate hearing from them.

         Pat Cassidy
         Indiana University

Bruno_Kieba.SBDERX@xerox.com (06/03/88)

Pat,
I would interested to see the source code of your semaphore implementation.  I
have myself implemented semaphores in MINIX but not as sophisticated as yours.
I wrote it for educational purpose only.  I implemented mine in the file system
of MINIX (because this is one area I am most familiar with) with three system
calls seminit, semwait and semsignal. To test it, I created a dummy file called
'data'.   First I do a 'initsem' (calling seminit) to initialise two semaphores
SPACE and WORK.  A producer (running in the background) does a semwait on a
semaphore SPACE, opens the file 'data', writes a number contained in a variable
into the file, increments the number contained in the variable by two for the
next  round, closes the file and does a semsignal on a  WORK semaphore.  A
consumer does a semwait on the WORK semaphore, opens the file 'data', retrieves
the number from it, displays it to the terminal screen, closes the file and does
a semsignal on the SPACE semaphore.  A consumer also runs in the background.
Both, producers and consumers need to run in the background otherwise they
cannot be killed  while they are executing.  The kill signal doesn't get caught.
The implementation works for one or more producers and consumers. Processes
waiting on a semaphore are blocked on the appropriate semaphore (FIFO) queue and
awaken when there is work to do (after a signal on the appropriate semaphore).
I used the 'trick' of Andy to do the implementation.  The only problem with my
implementation is that any process can initialise the WORK and SPACE semaphores
and thus totally screw up the blocked processes waiting on them.   I read about
the concept of keys UNIX uses. Maybe this is one way to do it.  I am interested
in the way you implemented your semaphores.  It will also help me to get more
familiar with the memory manager.  
The back pages of PC XENIX documentation show a few examples of semaphores in
order to test them.  The UNIX System Programming book from Keith Haviland and
Ben Salama (1987 Addison-Wesley Publishing Company, Inc.) has some examples for
shared memory with shmget and shmop system calls.  Good to look at.
Hoping that you can send me the source,
Bruno

cpm@datlog.co.uk (Paul Merriman) (06/09/88)

 	In response to the request for a simple test to semaphores :-

	As well as the Producer/Consumer type problem semaphores are useful
for providing synchronization between two or more  processes. A simple
test and illustration of this use would be to create two (very !) short 
prcesses - one which prints odd numbers and the other even numbers. Create
two semaphores (ODD and EVEN ?) and initialize them to 1 and 0 respectively.
Then 'wait's and 'signal's can be used to ensure that the processes output 
their numbers alternately (i.e. synchronizes the processes ) e.g.


	Process 1
	---------

	Wait(ODD)
	Print next odd number in sequence (1,3,5..)
	Signal(EVEN)


	Process 2
	---------

	WAIT(EVEN)
	Print next even number in sequence (2,4,6..)
	SIGNAL(ODD)


	While I'm on the subject I was interested to see that you implemented
the semaphores in mm. A nicer, but harder idea would be to put it in the fs
and then use file names to name your semaphores !