Lots of ideas to try (esp. since I don't need FIFO); thanks!
LPG
----- Original Message -----
From: "Terry Lambert" <[EMAIL PROTECTED]>
> Louis-Philippe Gagnon wrote:
> >
> > From: "Julian Elischer" <[EMAIL PROTECTED]>
> > > probably you should try :
> > >
> > > #define LOCK_NB 0x04 /* don't block when locking */
> > >
> > But I do want to block; I just don't want the whole process to block.
>
> You can't block just a thread, since there is no "queue a
> lock request" interface, only a "try to get the lock, and
> return if you can't" or a "block and wait for the lock".
>
> In other words, flock() is one call that can't really be
> reasonably implemented by the threads library, since
> there is no way to map it safely, and still guarantee
> against an order inversion deadlock.
>
>
> > > Also if you have shared memory, why not use
> > >
> > > /* Get a spin lock, handle recursion inline (as the less common case) */
>
>
> Using the "cmpxchgl" instruction is your best approach;
> I personally would not use the whole thing, as Julian
> suggested, since I think the SMP synchronization ops
> are much, much heavier than they should be. You don't
> need that much overhead, you don't need reentrancy, and
> you don't need it to do counting (neither does SMP).
>
> The easiest way to get shared memory is to use mmap() in
> both programs on a file, and to madvise() the caching and
> cache writeback off. This is much beeter than SYSV shared
> memory (shmat, shmget, etc.), since it is properly resource
> tracked, and you will not have a startup order of operation
> problem, nor will you have the common problem of trying to
> get rid of the segments, should any of your programs exit
> abnormally.
>
> > I'd rather have something portable though, and I would
> > still like to know if what I was doing should have worked...
>
> The answer is "no". Threads are not processes, they exist
> in a single process context, as they currently exist. In
> the future, what you are doing will work, but will have a
> very high comparative overhead to other approaches.
>
> If you read Stevens, you will see that flock() is much
> higher overhead than doing semop() calls.
>
> To wrap either, you would need to:
>
> retry:
> st = try_non_blocking_get();
> if (st == FAIL) {
> yield();
> goto retry;
> }
>
> Note that the "yield" system call is non-standard, and you
> will buzz-loop somewhat, depressing your priority. You
> will also have a race window, subject to the "thundering
> herd" problem. You could put a "sleep(1);" in place of
> the "yield();" call... this would eliminate the buzzing
> (somewhat), but would widen the race window.
>
> Another alternative is to use a multiended pipe, where
> you write a single character token down the pipe, and
> your programs block waiting for a single character read
> to complete (you could use a FIFO or socket, in place of
> the pipe). The point is that only a single reader can
> get the character (the "token") at a time.
>
> Unfortuantely, since file I/O is implemented as a
> conversion of a blocking call to a non-blocking call
> plus a context switch (normal for a threads library),
> you still have the "thundering herd" problem.
>
> Further, if your intent was to have the callers serviced
> in the order they called the read, you can't: you will
> never have a guarantee about who will be permitted to
> complete the read first.
>
> So, for FIFO ordering, there's no way for you to solve
> the problem; for semop or flock, you can solve the problem
> portably with a "sleep - retry" loop, and not burn too
> many cycles (but still lose FIFO ordering).
>
> If you absolutely _must_ have a FIFO, then you need to
> either wait, or install the Linux threads port (Linux
> threads are hideously expensive, compared to the current
> FreeBSD threads implementation, since they effectively
> create a new process for each thread, just like Linux
> does), and use blocking operations using them.
>
> Probably, if you need FIFO ordering, whatever you are
> doing would be better implemented as a finite state
> automaton, or a "work-to-do" model, where you don't
> really care who wins a race in a "thundering herd",
> since all of your programs waiting on the condition
> are identical.
>
> Worse comes to worse, you should consider implementing
> your threads as real seperate processes (and not fake
> ones, like in the Linux threads library).
>
> -- Terry
>
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message