<commit_before>/*-------------------------------------------------------------------------
 *
 * s_lock.c
 *	  Spinlock support routines
 *
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.33 2001/02/18 04:39:42 tgl Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <sys/time.h>
#include <unistd.h>

#include "miscadmin.h"
#include "storage/s_lock.h"


/*----------
 * Each time we busy spin we select the next element of this array as the
 * number of microseconds to wait. This accomplishes pseudo random back-off.
 *
 * Note that on most platforms, specified values will be rounded up to the
 * next multiple of a clock tick, which is often ten milliseconds (10000).
 * So, we are being way overoptimistic to assume that these different values
 * are really different, other than the last.  But there are a few platforms
 * with better-than-usual timekeeping, and on these we will get pretty good
 * pseudo-random behavior.
 *
 * Total time to cycle through all 20 entries will be at least 100 msec,
 * more commonly (10 msec resolution) 220 msec, and on some platforms
 * as much as 420 msec (when the remainder of the current tick cycle is
 * ignored in deciding when to time out, as on FreeBSD and older Linuxen).
 * We use the 100msec figure to figure max_spins, so actual timeouts may
 * be as much as four times the nominal value, but will never be less.
 *----------
 */
#define S_NSPINCYCLE	20

int			s_spincycle[S_NSPINCYCLE] =
{	1,		10,		100,	1000,
	10000,	1000,	1000,	1000,
	10000,	1000,	1000,	10000,
	1000,	1000,	10000,	1000,
	10000,	1000,	10000,	30000
};

#define AVG_SPINCYCLE	5000	/* average entry in microsec: 100ms / 20 */

#define DEFAULT_TIMEOUT	(100*1000000) /* default timeout: 100 sec */


/*
 * s_lock_stuck() - complain about a stuck spinlock
 */
static void
s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
{
	fprintf(stderr,
			"\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
			lock, file, line);
	fprintf(stdout,
			"\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
			lock, file, line);
	abort();
}


/*
 * s_lock_sleep() - sleep a pseudo-random amount of time, check for timeout
 *
 * The 'timeout' is given in microsec, or may be 0 for "infinity".  Note that
 * this will be a lower bound (a fairly loose lower bound, on most platforms).
 *
 * 'microsec' is the number of microsec to delay per loop.  Normally
 * 'microsec' is 0, specifying to use the next s_spincycle[] value.
 * Some callers may pass a nonzero interval, specifying to use exactly that
 * delay value rather than a pseudo-random delay.
 */
void
s_lock_sleep(unsigned spins, int timeout, int microsec,
			 volatile slock_t *lock,
			 const char *file, const int line)
{
	struct timeval delay;

	if (microsec > 0)
	{
		delay.tv_sec = 0;
		delay.tv_usec = microsec;
	}
	else
	{
		delay.tv_sec = 0;
		delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
		microsec = AVG_SPINCYCLE; /* use average to figure timeout */
	}

	if (timeout > 0)
	{
		unsigned	max_spins = timeout / microsec;

		if (spins > max_spins)
			s_lock_stuck(lock, file, line);
	}

	(void) select(0, NULL, NULL, NULL, &delay);
}


/*
 * s_lock(lock) - take a spinlock with backoff
 */<commit_msg>At least on HPUX, select with delay.tv_sec = 0 and delay.tv_usec = 1000000 does not lead to a one-second delay, but to an immediate EINVAL failure. This causes CHECKPOINT to crash with s_lock_stuck much too quickly :-(. Fix by breaking down the requested wait div/mod 1e6.<commit_after>/*-------------------------------------------------------------------------
 *
 * s_lock.c
 *	  Spinlock support routines
 *
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.34 2001/02/24 22:42:45 tgl Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <sys/time.h>
#include <unistd.h>

#include "miscadmin.h"
#include "storage/s_lock.h"


/*----------
 * Each time we busy spin we select the next element of this array as the
 * number of microseconds to wait. This accomplishes pseudo random back-off.
 *
 * Note that on most platforms, specified values will be rounded up to the
 * next multiple of a clock tick, which is often ten milliseconds (10000).
 * So, we are being way overoptimistic to assume that these different values
 * are really different, other than the last.  But there are a few platforms
 * with better-than-usual timekeeping, and on these we will get pretty good
 * pseudo-random behavior.
 *
 * Total time to cycle through all 20 entries will be at least 100 msec,
 * more commonly (10 msec resolution) 220 msec, and on some platforms
 * as much as 420 msec (when the remainder of the current tick cycle is
 * ignored in deciding when to time out, as on FreeBSD and older Linuxen).
 * We use the 100msec figure to figure max_spins, so actual timeouts may
 * be as much as four times the nominal value, but will never be less.
 *----------
 */
#define S_NSPINCYCLE	20

int			s_spincycle[S_NSPINCYCLE] =
{	1,		10,		100,	1000,
	10000,	1000,	1000,	1000,
	10000,	1000,	1000,	10000,
	1000,	1000,	10000,	1000,
	10000,	1000,	10000,	30000
};

#define AVG_SPINCYCLE	5000	/* average entry in microsec: 100ms / 20 */

#define DEFAULT_TIMEOUT	(100*1000000) /* default timeout: 100 sec */


/*
 * s_lock_stuck() - complain about a stuck spinlock
 */
static void
s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
{
	fprintf(stderr,
			"\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
			lock, file, line);
	fprintf(stdout,
			"\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
			lock, file, line);
	abort();
}


/*
 * s_lock_sleep() - sleep a pseudo-random amount of time, check for timeout
 *
 * The 'timeout' is given in microsec, or may be 0 for "infinity".  Note that
 * this will be a lower bound (a fairly loose lower bound, on most platforms).
 *
 * 'microsec' is the number of microsec to delay per loop.  Normally
 * 'microsec' is 0, specifying to use the next s_spincycle[] value.
 * Some callers may pass a nonzero interval, specifying to use exactly that
 * delay value rather than a pseudo-random delay.
 */
void
s_lock_sleep(unsigned spins, int timeout, int microsec,
			 volatile slock_t *lock,
			 const char *file, const int line)
{
	struct timeval delay;

	if (microsec > 0)
	{
		delay.tv_sec = microsec / 1000000;
		delay.tv_usec = microsec % 1000000;
	}
	else
	{
		delay.tv_sec = 0;
		delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
		microsec = AVG_SPINCYCLE; /* use average to figure timeout */
	}

	if (timeout > 0)
	{
		unsigned	max_spins = timeout / microsec;

		if (spins > max_spins)
			s_lock_stuck(lock, file, line);
	}

	(void) select(0, NULL, NULL, NULL, &delay);
}


/*
 * s_lock(lock) - take a spinlock with backoff
 */
{'fraction_non_alphanumeric': 0.13993362831858408, 'fraction_numerical': 0.04798119469026549, 'mean_word_length': 2.980737479361585, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7373327', 'n_tokens_mistral': 2692, 'n_tokens_neox': 2315, 'n_words': 904}