mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 08:12:28 +00:00
Make more improvements to threads and mappings
- NetBSD should now have faster synchronization - POSIX barriers may now be shared across processes - An edge case with memory map tracking has been fixed - Grand Central Dispatch is no longer used on MacOS ARM64 - POSIX mutexes in normal mode now use futexes across processes
This commit is contained in:
parent
2187d6d2dd
commit
e398f3887c
20 changed files with 566 additions and 171 deletions
|
@ -16,25 +16,53 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/blockcancel.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "third_party/nsync/counter.h"
|
||||
#include "third_party/nsync/futex.internal.h"
|
||||
|
||||
/**
|
||||
* Waits for all threads to arrive at barrier.
|
||||
*
|
||||
* When the barrier is broken, the state becomes reset to what it was
|
||||
* when pthread_barrier_init() was called, so that the barrior may be
|
||||
* used again in the same way. The last thread to arrive shall be the
|
||||
* last to leave and it returns a magic value.
|
||||
* used again in the same way.
|
||||
*
|
||||
* Unlike pthread_cond_timedwait() this function is not a cancelation
|
||||
* point. It is not needed to have cleanup handlers on block cancels.
|
||||
*
|
||||
* @return 0 on success, `PTHREAD_BARRIER_SERIAL_THREAD` to one lucky
|
||||
* thread which was the last arrival, or an errno on error
|
||||
* @raise EINVAL if barrier is used incorrectly
|
||||
*/
|
||||
errno_t pthread_barrier_wait(pthread_barrier_t *barrier) {
|
||||
if (nsync_counter_add(barrier->_nsync, -1)) {
|
||||
nsync_counter_wait(barrier->_nsync, nsync_time_no_deadline);
|
||||
return 0;
|
||||
} else {
|
||||
int n;
|
||||
|
||||
// enter barrier
|
||||
atomic_fetch_add_explicit(&barrier->_waiters, 1, memory_order_acq_rel);
|
||||
n = atomic_fetch_sub_explicit(&barrier->_counter, 1, memory_order_acq_rel);
|
||||
n = n - 1;
|
||||
|
||||
// this can only happen on invalid usage
|
||||
if (n < 0)
|
||||
return EINVAL;
|
||||
|
||||
// reset count and wake waiters if we're last at barrier
|
||||
if (!n) {
|
||||
atomic_store_explicit(&barrier->_counter, barrier->_count,
|
||||
memory_order_release);
|
||||
atomic_store_explicit(&barrier->_waiters, 0, memory_order_release);
|
||||
nsync_futex_wake_(&barrier->_waiters, INT_MAX, barrier->_pshared);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
|
||||
// wait for everyone else to arrive at barrier
|
||||
BLOCK_CANCELATION;
|
||||
while ((n = atomic_load_explicit(&barrier->_waiters, memory_order_acquire)))
|
||||
nsync_futex_wait_(&barrier->_waiters, n, barrier->_pshared, 0);
|
||||
ALLOW_CANCELATION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue