6.8 Exercise: Barriers

Team-FLY

A barrier is a synchronization construct used by cooperating processes to block until all processes reach a particular point. The exercises in this section use a FIFO to implement a barrier. They extend the simple barrier of Program 6.2.

Write a barrier server that takes two command-line arguments: the name of a barrier ( name ) and the size of the barrier ( n ). The size represents the number of processes that need to block at that barrier. The server creates a named pipe, name.request , to handle requests for the barrier and a named pipe, name.release , for writing the release characters . For example, if the barrier name is mybarrier , the server creates pipes called mybarrier.request and mybarrier.release . The server then does the following in a loop.

  1. Open name.request for reading.

  2. Read exactly n characters from name.request .

  3. Close name.request .

  4. Open name.release for writing.

  5. Write exactly n characters to name.release .

  6. Close name.release .

Write the following barrier function for use by the clients .

 int waitatbarrier(char *name); 

The function blocks at the barrier with the given name. If successful, the waitatbarrier function returns 0. If unsuccessful , waitatbarrier returns 1 and sets errno . The waitatbarrier does the following in a loop.

  1. Open name.request for writing.

  2. Write one byte to name.request .

  3. Close name.request .

  4. Open name.release for reading.

  5. Read one byte from name.release .

  6. Close name.release .

Be sure that waitatbarrier closes any pipe that it opens, even if an error occurs. If an error occurs on a read or write , save the value of errno , close the pipe, restore errno and return 1.

This function works because of the way blocking is done when a pipe is opened. An open operation for read will block until at least one process has called open for writing. Similarly, an open operation for write will block until at least one process called open for reading. The client will block on the open of the request pipe until the server has opened it. It will then block on the open of the release pipe until the server has read the bytes from all of the other processes and opened the release pipe for writing. A second attempt to use the barrier with the same name will block on the open of the request pipe until all of the processes have passed the first barrier since the server has closed the request pipe.

Test your clients and server by modifying the process chain of Program 3.1 on page 67 or the process fan of Program 3.2 on page 68. Have each one use the same named barrier several times. Each time they wait at the barrier, they should print a message. If the modification is working correctly, all the first messages should be printed before any of the second ones. Are there any circumstances under which reusing a barrier can fail?

Generalize your barrier server to handle many different barriers. You should still have one request pipe. The clients send the name and size of the barrier they are requesting in a single write to the request pipe. The server keeps a dynamic list of the barriers. If a request for a new barrier comes in, the server creates a new release pipe, adds this barrier to its list, and creates a child process to handle the barrier. If a request for an old barrier comes in, it is ignored.

Clients can create as many barriers as they need, but each client now has to know how many other clients there are. Alternatively, the server can be given the number of clients on the command line when it starts up. See if you can devise a mechanism for the server to find out from the clients how many they are. Be careful, this is not easy.

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net