Date: Thu, 19 Jul 2001 09:46:27 -0400 From: "Louis-Philippe Gagnon" <louisphilippe@macadamian.com> To: <tlambert2@mindspring.com> Cc: <freebsd-hackers@FreeBSD.ORG> Subject: Re: flock/pthread bug? Message-ID: <203501c11059$35755420$2964a8c0@macadamian.com> References: <Pine.BSF.4.21.0107181320030.94740-100000@InterJet.elischer.org> <1fbd01c10fba$499834d0$2964a8c0@macadamian.com> <3B5690A1.8EDD0812@mindspring.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Lots of ideas to try (esp. since I don't need FIFO); thanks! LPG ----- Original Message ----- From: "Terry Lambert" <tlambert2@mindspring.com> > Louis-Philippe Gagnon wrote: > > > > From: "Julian Elischer" <julian@elischer.org> > > > 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 majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?203501c11059$35755420$2964a8c0>