![](https://csdnimg.cn/release/download_crawler_static/10909249/bg4.jpg)
Ottawa Linux Symposium 2002 482
It is desirable to have the user lock be handle-
free. In other words instead of handling an
oqaque kernel handle, requiring initialization
and cross process global handles, it is desir-
able to address locks directly through their vir-
tual address. As a consequence, kernel objects
can be allocated dynamically and on demand,
rather than apriori.
A lock, though addressed by a virtual ad-
dress, can be identified conceptually through
its global lock identity, which we define by the
memory object backing the virtual address and
the offset within that object. We notate this
by the tuple [B,O]. Three fundamental mem-
ory types can be distinguished that represent
B: (a) anonymous memory, (b) shared memory
segment, and (c) memory mapped files. While
(b) and (c) can be used between multiple pro-
cesses, (a) can only be used between threads
of the same process. Utilizing the virtual ad-
dress of the lock as the kernel handle also pro-
vides for an integrated access mechanism that
ties the virtual address automatically with its
kernel object.
Despite the atomic manipulation of the user
level lock word, race conditions can still ex-
ists as the sequence of lock word manipulation
and system calls is not atomic. This has to
be resolved properly within the kernel to avoid
deadlock and inproper functioning.
Another requirement is that fast user level lock-
ing should be simple enough to provide the
basic foundation to efficiently enable more
complicated synchronization constructs, e.g.
semaphores, rwlocks, blocking locks, or spin
versions of these, pthread mutexes, DB latches.
It should also allow for a clean separation
of the blocking requirements towards the ker-
nel, so that the blocking only has to be im-
plemented with a small set of different con-
structs. This allows for extending the use of
the basic primitives without kernel modifica-
tions. Of interest is the implementation of
mutex, semaphores and multiple reader/single
writer locks.
Finally, a solution needs to be found that en-
ables the recovery of “dead” locks. We define
unrecoverable locks as those that have been ac-
quired by a process and the process terminates
without releasing the lock. There are no conve-
nient means for the kernel or for the other pro-
cesses to determine which locks are currently
held by a particular process, as lock acquisition
can be achieved through user memory manip-
ulation. Registering the process’s “pid” after
lock acquisition is not enough as both opera-
tions are not atomic. If the process dies before
it can register its pid or if it cleared its pid and
before being able the release the lock, the lock
is unrecoverable. A protocol based solution to
this problem is described in [1]. We have not
addressed this problem in our prototypes yet.
3 Linux Fast User level Locking:
History and Implementations
Having stated the requirements in the previ-
ous section, we now proceed to describe the
basic general implementation issues. For the
purpose of this discussion we define a gen-
eral opaque datatype ulock_t to represent
the userlevel lock. At a minimum it requires
a status word.
typedef struct ulock_t {
long status;
} ulock_t;
We assume that a shared memory region has
been allocated either through shmat() or
through mmap() and that any user locks are
allocated into this region. Again note, that the
addresses of the same lock need not be the
same across all participating address spaces.