<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// A simple barrier sync.

"use strict";

//////////////////////////////////////////////////////////////////////
//
// Barriers.
//
// Barriers are JS objects that use some shared memory for private
// data.  The number of shared int32 locations needed is given by
// Barrier.NUMINTS.  The shared memory for a barrier should be
// initialized once by calling Barrier.initialize() on the memory,
// before constructing the first Barrier object in any agent.

// Create a barrier object.
//
// 'iab' is a SharedInt32Array.
// 'ibase' is the first of Barrier.NUMINTS slots within iab reserved
// for the barrier.
//
// iab and ibase will be exposed on the Barrier.
function Barrier(iab, ibase) {
    if (!(iab instanceof SharedInt32Array && ibase|0 == ibase && ibase >= 0 && ibase+Barrier.NUMINTS <= iab.length))
	throw new Error("Bad arguments to Barrier constructor: " + iab + " " + ibase);
    this.iab = iab;
    this.ibase = ibase;
}

// Number of shared Int32 locations needed by the barrier.
Barrier.NUMINTS = 3;

// Initialize the shared memory for a barrier.
//
// 'iab' is a SharedInt32Array.
// 'ibase' is the first of Barrier.NUMINTS slots within iab reserved
// for the barrier.
// 'numAgents' is the number of participants in the barrier.
//
// Returns 'ibase'.
Barrier.initialize =
    function (iab, ibase, numAgents) {
	if (!(iab instanceof SharedInt32Array &&
	      ibase|0 == ibase &&
	      ibase >= 0 &&
	      ibase+Barrier.NUMINTS <= iab.length &&
	      numAgents|0 == numAgents))
	{
	    throw new Error("Bad arguments to Barrier initializer: " + iab + " " + ibase + " " + numAgents);
	}

	const counterLoc = ibase;
	const seqLoc = ibase+1;
	const numAgentsLoc = ibase+2;

	Atomics.store(iab, counterLoc, numAgents);
	Atomics.store(iab, seqLoc, 0);
	Atomics.store(iab, numAgentsLoc, numAgents);

	return ibase;
    };

// Enter the barrier.  This will block until all agents have entered
// the barrier, at which point all agents are automatically released.
// The barrier is then immediately usable.
Barrier.prototype.enter =
    function () {
	const iab = this.iab;
	const ibase = this.ibase;

	const counterLoc = ibase;
	const seqLoc = ibase+1;
	const numAgentsLoc = ibase+2;

	if (Atomics.sub(iab, counterLoc, 1) == 1) {
	    const numAgents = iab[numAgentsLoc];
	    Atomics.store(iab, counterLoc, numAgents);
	    Atomics.add(iab, seqLoc, 1);
	    // The correctness of the wakeup call depends on the
	    // linear-queue behavior of wait and wake: we wake the
	    // numAgents-1 that are currently waiting, even if some
	    // agents might reenter the barrier and start waiting
	    // again before the waking is finished.
	    Atomics.futexWake(iab, seqLoc, numAgents-1);
	}
	else {
	    const seq = Atomics.load(iab, seqLoc);
	    Atomics.futexWait(iab, seqLoc, seq, Number.POSITIVE_INFINITY);
	}
    };
<commit_msg>Fix a bug: the sequence number must be read before the last-worker-in test, or there is a race<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// A simple barrier sync.

"use strict";

//////////////////////////////////////////////////////////////////////
//
// Barriers.
//
// Barriers are JS objects that use some shared memory for private
// data.  The number of shared int32 locations needed is given by
// Barrier.NUMINTS.  The shared memory for a barrier should be
// initialized once by calling Barrier.initialize() on the memory,
// before constructing the first Barrier object in any agent.

// Create a barrier object.
//
// 'iab' is a SharedInt32Array.
// 'ibase' is the first of Barrier.NUMINTS slots within iab reserved
// for the barrier.
//
// iab and ibase will be exposed on the Barrier.
function Barrier(iab, ibase) {
    if (!(iab instanceof SharedInt32Array && ibase|0 == ibase && ibase >= 0 && ibase+Barrier.NUMINTS <= iab.length))
	throw new Error("Bad arguments to Barrier constructor: " + iab + " " + ibase);
    this.iab = iab;
    this.ibase = ibase;
}

// Number of shared Int32 locations needed by the barrier.
Barrier.NUMINTS = 3;

// Initialize the shared memory for a barrier.
//
// 'iab' is a SharedInt32Array.
// 'ibase' is the first of Barrier.NUMINTS slots within iab reserved
// for the barrier.
// 'numAgents' is the number of participants in the barrier.
//
// Returns 'ibase'.
Barrier.initialize =
    function (iab, ibase, numAgents) {
	if (!(iab instanceof SharedInt32Array &&
	      ibase|0 == ibase &&
	      ibase >= 0 &&
	      ibase+Barrier.NUMINTS <= iab.length &&
	      numAgents|0 == numAgents))
	{
	    throw new Error("Bad arguments to Barrier initializer: " + iab + " " + ibase + " " + numAgents);
	}

	const counterLoc = ibase;
	const seqLoc = ibase+1;
	const numAgentsLoc = ibase+2;

	Atomics.store(iab, counterLoc, numAgents);
	Atomics.store(iab, seqLoc, 0);
	Atomics.store(iab, numAgentsLoc, numAgents);

	return ibase;
    };

// Enter the barrier.  This will block until all agents have entered
// the barrier, at which point all agents are automatically released.
// The barrier is then immediately usable.
Barrier.prototype.enter =
    function () {
	const iab = this.iab;
	const ibase = this.ibase;

	const counterLoc = ibase;
	const seqLoc = ibase+1;
	const numAgentsLoc = ibase+2;

	// The sequence number must be read before the check, otherwise
	// when we wait there is the possibility that the waiting thread
	// will read the sequence number that has been updated by the
	// non-waiting thread, and incorrectly wait on that.
	const seq = Atomics.load(iab, seqLoc);
	if (Atomics.sub(iab, counterLoc, 1) == 1) {
	    const numAgents = iab[numAgentsLoc];
	    iab[counterLoc] = numAgents;
	    iab[seqLoc] = seq+1;
	    // The correctness of the wakeup call depends on the
	    // linear-queue behavior of wait and wake: we wake the
	    // numAgents-1 that are currently waiting, even if some
	    // agents might reenter the barrier and start waiting
	    // again before the waking is finished.
	    Atomics.futexWake(iab, seqLoc, numAgents-1);
	}
	else {
	    Atomics.futexWait(iab, seqLoc, seq, Number.POSITIVE_INFINITY);
	}
    };

{'fraction_non_alphanumeric': 0.12676493405740885, 'fraction_numerical': 0.009930178432893715, 'mean_word_length': 2.880794701986755, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6763930', 'n_tokens_mistral': 2116, 'n_tokens_neox': 1958, 'n_words': 752}