30.8 TCP Preforked
Server, Thread Locking Around accept
As we mentioned, there are various ways to
implement locking between processes. The POSIX file locking in the
previous section is portable to all POSIX-compliant systems, but it
involves filesystem operations, which can take time. In this
section, we will use thread locking, taking advantage of the fact
that this can be used not only for locking between the threads
within a given process, but also for locking between different
processes.
Our main function remains the same as
in the previous section, as do our child_make and
child_main functions. The only thing that changes is our
three locking functions. To use thread locking between different
processes requires that: (i) the mutex variable must be stored in
memory that is shared between all the processes; and (ii) the
thread library must be told that the mutex is shared among
different processes.
Also, the thread library must support the
PTHREAD_PROCESS_SHARED attribute.
There are various ways to share memory between
different processes, as we described in the second volume of this
series. In our example, we will use the mmap function with
the /dev/zero device, which works under Solaris and other
SVR4 kernels. Figure 30.18
shows our my_lock_init function.
Figure 30.18
my_lock_init function using Pthread locking between
processes.
server/lock_pthread.c
1 #include "unpthread.h"
2 #include <sys/mman.h>
3 static pthread_mutex_t *mptr; /* actual mutex will be in shared memory */
4 void
5 my_lock_init(char *pathname)
6 {
7 int fd;
8 pthread_mutexattr_t mattr;
9 fd = Open("/dev/zero", O_RDWR, 0);
10 mptr = Mmap(0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE,
11 MAP_SHARED, fd, 0);
12 Close(fd);
13 Pthread_mutexattr_init(&mattr);
14 Pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
15 Pthread_mutex_init(mptr, &mattr);
16 }
9鈥?2
We open/dev/zero and then call mmap. The number
of bytes that are mapped is equal to the size of a
pthread_mutex_t variable. The descriptor is then closed,
which is fine, because the memory mapped to /dev/zero will
remain mapped.
13鈥?5
In our previous Pthread mutex examples, we initialized the global
or static mutex variable using the constant
PTHREAD_MUTEX_INITIALIZER (e.g., Figure 26.18). But
with a mutex in shared memory, we must call some Pthread library
functions to tell the library that the mutex is in shared memory
and that it will be used for locking between different processes.
We first initialize a pthread_mutexattr_t structure with
the default attributes for a mutex and then set the
PTHREAD_PROCESS_SHARED attribute. (The default for this
attribute is PTHREAD_PROCESS_PRIVATE, allowing use only
within a single process.) pthread_mutex_init then
initializes the mutex with these attributes.
Figure 30.19 shows our
my_lock_wait and my_lock_release functions. Each
is now just a call to a Pthread function to lock or unlock the
mutex.
Comparing rows 3 and 4 in Figure 30.1 for
the Solaris server shows that thread mutex locking is faster than
file locking.
|