On Tue, 2013-03-26 at 11:19 -0400, Rik van Riel wrote: > > Maybe something like: > > > > void sma_lock(struct sem_array *sma) /* global */ > > { > > int i; > > > > sma->global_locked = 1; > > smp_wmb(); /* can we merge with the LOCK ? */ > > spin_lock(&sma->global_lock); > > > > /* wait for all local locks to go away */ > > for (i = 0; i < sma->sem_nsems; i++) > > spin_unlock_wait(&sem->sem_base[i]->lock); > > } > > > > void sma_lock_one(struct sem_array *sma, int nr) /* local */ > > { > > smp_rmb(); /* pairs with wmb in sma_lock() */ > > if (unlikely(sma->global_locked)) { /* wait for global lock */ > > while (sma->global_locked) > > spin_unlock_wait(&sma->global_lock); > > } > > spin_lock(&sma->sem_base[nr]->lock); > > }
I since realized there's an ordering problem with ->global_locked, we need to use spin_is_locked() or somesuch. Two competing sma_lock() operations will screw over the separate variable. > > > This still has the problem of a non-preemptible section of > O(sem_nsems) > > (with the avg wait-time on the local lock). Could we make the global > > lock a sleeping lock? > > Not without breaking your scheme above :) How would making sma->global_lock a mutex wreck anything? -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/