<commit_before>/*
 * Copyright (c) 1995-1998 <NAME> <<EMAIL>>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by <NAME>.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY <NAME> AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 *
 */
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <pthread.h>
#include "pthread_private.h"

/* #define DEBUG_THREAD_KERN */
#ifdef DEBUG_THREAD_KERN
#define DBG_MSG		stdout_debug
#else
#define DBG_MSG(x...)
#endif

/* Static function prototype definitions: */
static void
thread_kern_poll(int wait_reqd);

static void
dequeue_signals(void);

static inline void
thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in);

/* Static variables: */
static int	last_tick = 0;
static int	called_from_handler = 0;

/*
 * This is called when a signal handler finishes and wants to
 * return to a previous frame.
 */
void
_thread_kern_sched_frame(struct pthread_signal_frame *psf)
{
	struct pthread	*curthread = _get_curthread();

	/*
	 * Flag the pthread kernel as executing scheduler code
	 * to avoid a signal from interrupting this execution and
	 * corrupting the (soon-to-be) current frame.
	 */
	_thread_kern_in_sched = 1;

	/* Restore the signal frame: */
	_thread_sigframe_restore(curthread, psf);

	/* The signal mask was restored; check for any pending signals: */
	curthread->check_pending = 1;

	/* Switch to the thread scheduler: */
	___longjmp(_thread_kern_sched_jb, 1);
}


void
_thread_kern_sched(ucontext_t *ucp)
{
	struct pthread	*curthread = _get_curthread();

	/*
	 * Flag the pthread kernel as executing scheduler code
	 * to avoid a scheduler signal from interrupting this
	 * execution and calling the scheduler again.
	 */
	_thread_kern_in_sched = 1;

	/* Check if this function was called from the signal handler: */
	if (ucp != NULL) {
#if 1
		/* XXX - Save FP registers? */
		FP_SAVE_UC(ucp);
#endif
		called_from_handler = 1;
		DBG_MSG("Entering scheduler due to signal\n");
	}

	/* Save the state of the current thread: */
	if (_setjmp(curthread->ctx.jb) != 0) {
		DBG_MSG("Returned from ___longjmp, thread %p\n",
		    curthread);
		/*
		 * This point is reached when a longjmp() is called
		 * to restore the state of a thread.
		 *
		 * This is the normal way out of the scheduler.
		 */
		_thread_kern_in_sched = 0;

		if (curthread->sig_defer_count == 0) {
			if (((curthread->cancelflags &
			    PTHREAD_AT_CANCEL_POINT) == 0) &&
			    ((curthread->cancelflags &
			    PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
				/*
				 * Cancellations override signals.
				 *
				 * Stick a cancellation point at the
				 * start of each async-cancellable
				 * thread's resumption.
				 *
				 * We allow threads woken at cancel
				 * points to do their own checks.
				 */
				pthread_testcancel();
		}

		if (_sched_switch_hook != NULL) {
			/* Run the installed switch hook: */
			thread_run_switch_hook(_last_user_thread, curthread);
		}
		if (ucp == NULL)
			return;
		else {
#if 1
			/* XXX - Restore FP registers? */
			FP_RESTORE_UC(ucp);
#endif

			/*
			 * Set the process signal mask in the context; it
			 * could have changed by the handler.
			 */
			ucp->uc_sigmask = _process_sigmask;

			/* Resume the interrupted thread: */
			__sys_sigreturn(ucp);
		}
	}
	/* Switch to the thread scheduler: */
	___longjmp(_thread_kern_sched_jb, 1);
}

void
_thread_kern_sched_sig(void)
{
	struct pthread	*curthread = _get_curthread();

	curthread->check_pending = 1;
	_thread_kern_sched(NULL);<commit_msg>Once again, remove the i386-specific hacks to save and restore the FPU state on receiving and returning from a signal. The FPU save and restore macros are no longer needed, but remain defined in case we need to use them again (something else breaks).  They'll be removed permanently once new syscalls are added to handle the new i386 ucontext size.<commit_after>/*
 * Copyright (c) 1995-1998 <NAME> <<EMAIL>>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by <NAME>.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY <NAME> AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 *
 */
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <pthread.h>
#include "pthread_private.h"

/* #define DEBUG_THREAD_KERN */
#ifdef DEBUG_THREAD_KERN
#define DBG_MSG		stdout_debug
#else
#define DBG_MSG(x...)
#endif

/* Static function prototype definitions: */
static void
thread_kern_poll(int wait_reqd);

static void
dequeue_signals(void);

static inline void
thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in);

/* Static variables: */
static int	last_tick = 0;
static int	called_from_handler = 0;

/*
 * This is called when a signal handler finishes and wants to
 * return to a previous frame.
 */
void
_thread_kern_sched_frame(struct pthread_signal_frame *psf)
{
	struct pthread	*curthread = _get_curthread();

	/*
	 * Flag the pthread kernel as executing scheduler code
	 * to avoid a signal from interrupting this execution and
	 * corrupting the (soon-to-be) current frame.
	 */
	_thread_kern_in_sched = 1;

	/* Restore the signal frame: */
	_thread_sigframe_restore(curthread, psf);

	/* The signal mask was restored; check for any pending signals: */
	curthread->check_pending = 1;

	/* Switch to the thread scheduler: */
	___longjmp(_thread_kern_sched_jb, 1);
}


void
_thread_kern_sched(ucontext_t *ucp)
{
	struct pthread	*curthread = _get_curthread();

	/*
	 * Flag the pthread kernel as executing scheduler code
	 * to avoid a scheduler signal from interrupting this
	 * execution and calling the scheduler again.
	 */
	_thread_kern_in_sched = 1;

	/* Check if this function was called from the signal handler: */
	if (ucp != NULL) {
		called_from_handler = 1;
		DBG_MSG("Entering scheduler due to signal\n");
	}

	/* Save the state of the current thread: */
	if (_setjmp(curthread->ctx.jb) != 0) {
		DBG_MSG("Returned from ___longjmp, thread %p\n",
		    curthread);
		/*
		 * This point is reached when a longjmp() is called
		 * to restore the state of a thread.
		 *
		 * This is the normal way out of the scheduler.
		 */
		_thread_kern_in_sched = 0;

		if (curthread->sig_defer_count == 0) {
			if (((curthread->cancelflags &
			    PTHREAD_AT_CANCEL_POINT) == 0) &&
			    ((curthread->cancelflags &
			    PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
				/*
				 * Cancellations override signals.
				 *
				 * Stick a cancellation point at the
				 * start of each async-cancellable
				 * thread's resumption.
				 *
				 * We allow threads woken at cancel
				 * points to do their own checks.
				 */
				pthread_testcancel();
		}

		if (_sched_switch_hook != NULL) {
			/* Run the installed switch hook: */
			thread_run_switch_hook(_last_user_thread, curthread);
		}
		if (ucp == NULL)
			return;
		else {
			/*
			 * Set the process signal mask in the context; it
			 * could have changed by the handler.
			 */
			ucp->uc_sigmask = _process_sigmask;

			/* Resume the interrupted thread: */
			__sys_sigreturn(ucp);
		}
	}
	/* Switch to the thread scheduler: */
	___longjmp(_thread_kern_sched_jb, 1);
}

void
_thread_kern_sched_sig(void)
{
	struct pthread	*curthread = _get_curthread();

	curthread->check_pending = 1;
	_thread_kern_sched(NULL);
{'fraction_non_alphanumeric': 0.09004256894317972, 'fraction_numerical': 0.00555247084952804, 'mean_word_length': 3.7988454706927177, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 61, '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': '2626860', 'n_tokens_mistral': 3670, 'n_tokens_neox': 3224, 'n_words': 1230}