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 !