On Tue, 22 May 2001 07:56:52 -0700 (PDT),
  John Baldwin <[EMAIL PROTECTED]> said:

John> On 22-May-01 Seigo Tanimura wrote:
>> On Tue, 22 May 2001 04:48:38 -0700 (PDT),
>> John Baldwin <[EMAIL PROTECTED]> said:
John> On 22-May-01 Seigo Tanimura wrote:
>>>> For now, p_mtx protects p_pgrp in struct proc. This is quite
>>>> troublesome for the following reason:
John> Err, it doesn't really.  It's mostly undecided at this point.  Also, have you
John> looked at the BSD/OS code on builder?  They have process groups and sessions
John> already locked not using global locks but using per-data structure locks.
>> If you do not protect both p_pgrp and p_pglist in struct proc by an
>> identical lock, you end up with breaking either setpgid(2) or kill(2)
>> for a process group. The following scenario depicts an example of the
>> breakage:

John> I'll have to look over the code in more detail, but I would encourage you
John> to check the BSD/OS code.

I did that last night, and figured out that there are two problems in
FreeBSD under the scenario shown below:

1. Lock a process and obtain a process group via p_pgrp.
2. Lock the process list of the process group and traverse the list
   via p_pglist, locking each process in the list.
3. Lock each process in the list.

That scenario induces the following problems:

A. We have to lock two processes at once in order to traverse the
   list, namely p and LIST_NEXT(p, p_pglist) where p is a process in
   the list.

B. We have to lock a process in 1 and 3 while locking a process group
   in 2, resulting in lock order reversal.

BSD/OS solves the problem A by locking not a process but a process
group to traverse the list. It should be worth implementing that
solution in FreeBSD.

In order to solve the problem B, a lock other than the process lock
should protect p_pgrp. BSD/OS adopts the lock of a session accessible
via p_session embedded in struct proc, while I attempt to apply a
global lock. In any case, the aim of the p_pgrp lock is essentially
for protecting *only* p_pgrp. Once we lock p_pgrp, we can compare
pg_session (which requires no locks), lock a process group, a session
or etc. until unlocking p_pgrp.

The issue of both of the solutions briefed above is that the p_pgrp
lock protects *excess* data. It might be another solution to introduce
a new mutex (p_pgrpmtx) into struct proc to lock p_pgrp. Although
memory size costs per process, contention for p_pgrp lock should occur
much less than to adopt a session lock or a global lock.

As psignal() and some other functions also read p_pgrp, p_mtx should
also lock p_pgrp. You lock either p_pgrpmtx or p_mtx to read p_pgrp,
and both of the locks to modify p_pgrp.


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to