sync code with last fixes and improvements from OpenBSD

This commit is contained in:
purplerain 2023-08-08 00:42:18 +00:00
parent 691f97cc10
commit 371ae113c6
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
175 changed files with 2932 additions and 1512 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: kern_clock.c,v 1.109 2023/07/25 18:16:19 cheloha Exp $ */
/* $OpenBSD: kern_clock.c,v 1.111 2023/08/05 20:07:55 cheloha Exp $ */
/* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */
/*-
@ -84,7 +84,8 @@ int profhz;
int profprocs;
int ticks = INT_MAX - (15 * 60 * HZ);
volatile unsigned long jiffies = ULONG_MAX - (10 * 60 * HZ);
/* Don't force early wrap around, triggers bug in inteldrm */
volatile unsigned long jiffies;
/*
* Initialize clock frequencies and start both clocks running.
@ -104,43 +105,14 @@ initclocks(void)
inittimecounter();
}
/*
* hardclock does the accounting needed for ITIMER_PROF and ITIMER_VIRTUAL.
* We don't want to send signals with psignal from hardclock because it makes
* MULTIPROCESSOR locking very complicated. Instead, to use an idea from
* FreeBSD, we set a flag on the thread and when it goes to return to
* userspace it signals itself.
*/
/*
* The real-time timer, interrupting hz times per second.
*/
void
hardclock(struct clockframe *frame)
{
struct proc *p;
struct cpu_info *ci = curcpu();
p = curproc;
if (p && ((p->p_flag & (P_SYSTEM | P_WEXIT)) == 0)) {
struct process *pr = p->p_p;
/*
* Run current process's virtual and profile time, as needed.
*/
if (CLKF_USERMODE(frame) &&
timespecisset(&pr->ps_timer[ITIMER_VIRTUAL].it_value) &&
itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], tick_nsec) == 0) {
atomic_setbits_int(&p->p_flag, P_ALRMPEND);
need_proftick(p);
}
if (timespecisset(&pr->ps_timer[ITIMER_PROF].it_value) &&
itimerdecr(&pr->ps_timer[ITIMER_PROF], tick_nsec) == 0) {
atomic_setbits_int(&p->p_flag, P_PROFPEND);
need_proftick(p);
}
}
if (--ci->ci_schedstate.spc_rrticks <= 0)
roundrobin(ci);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: kern_clockintr.c,v 1.29 2023/07/27 17:52:53 cheloha Exp $ */
/* $OpenBSD: kern_clockintr.c,v 1.30 2023/08/05 20:07:55 cheloha Exp $ */
/*
* Copyright (c) 2003 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@ -196,6 +196,10 @@ clockintr_cpu_init(const struct intrclock *ic)
* XXX Need to find a better place to do this. We can't do it in
* sched_init_cpu() because initclocks() runs after it.
*/
if (spc->spc_itimer->cl_expiration == 0) {
clockintr_stagger(spc->spc_itimer, hardclock_period,
multiplier, MAXCPUS);
}
if (spc->spc_profclock->cl_expiration == 0) {
clockintr_stagger(spc->spc_profclock, profclock_period,
multiplier, MAXCPUS);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: kern_sched.c,v 1.81 2023/07/27 17:52:53 cheloha Exp $ */
/* $OpenBSD: kern_sched.c,v 1.84 2023/08/05 20:07:55 cheloha Exp $ */
/*
* Copyright (c) 2007, 2008 Artur Grabowski <art@openbsd.org>
*
@ -24,6 +24,7 @@
#include <sys/clockintr.h>
#include <sys/resourcevar.h>
#include <sys/task.h>
#include <sys/time.h>
#include <sys/smr.h>
#include <sys/tracepoint.h>
@ -87,6 +88,14 @@ sched_init_cpu(struct cpu_info *ci)
spc->spc_idleproc = NULL;
if (spc->spc_itimer == NULL) {
spc->spc_itimer = clockintr_establish(&ci->ci_queue,
itimer_update);
if (spc->spc_itimer == NULL) {
panic("%s: clockintr_establish itimer_update",
__func__);
}
}
if (spc->spc_profclock == NULL) {
spc->spc_profclock = clockintr_establish(&ci->ci_queue,
profclock);
@ -223,6 +232,10 @@ sched_exit(struct proc *p)
timespecsub(&ts, &spc->spc_runtime, &ts);
timespecadd(&p->p_rtime, &ts, &p->p_rtime);
if (ISSET(spc->spc_schedflags, SPCF_ITIMER)) {
atomic_clearbits_int(&spc->spc_schedflags, SPCF_ITIMER);
clockintr_cancel(spc->spc_itimer);
}
if (ISSET(spc->spc_schedflags, SPCF_PROFCLOCK)) {
atomic_clearbits_int(&spc->spc_schedflags, SPCF_PROFCLOCK);
clockintr_cancel(spc->spc_profclock);
@ -262,7 +275,6 @@ setrunqueue(struct cpu_info *ci, struct proc *p, uint8_t prio)
KASSERT(ci != NULL);
SCHED_ASSERT_LOCKED();
KASSERT(!ISSET(p->p_flag, P_WSLEEP) || p->p_stat == SSTOP);
p->p_cpu = ci;
p->p_stat = SRUN;
@ -373,7 +385,6 @@ sched_choosecpu_fork(struct proc *parent, int flags)
{
#ifdef MULTIPROCESSOR
struct cpu_info *choice = NULL;
fixpt_t load, best_load = ~0;
int run, best_run = INT_MAX;
struct cpu_info *ci;
struct cpuset set;
@ -407,13 +418,10 @@ sched_choosecpu_fork(struct proc *parent, int flags)
while ((ci = cpuset_first(&set)) != NULL) {
cpuset_del(&set, ci);
load = ci->ci_schedstate.spc_ldavg;
run = ci->ci_schedstate.spc_nrun;
if (choice == NULL || run < best_run ||
(run == best_run &&load < best_load)) {
if (choice == NULL || run < best_run) {
choice = ci;
best_load = load;
best_run = run;
}
}
@ -606,11 +614,6 @@ sched_proc_to_cpu_cost(struct cpu_info *ci, struct proc *p)
if (CPU_IS_PRIMARY(ci))
cost += sched_cost_runnable;
/*
* Higher load on the destination means we don't want to go there.
*/
cost += ((sched_cost_load * spc->spc_ldavg) >> FSHIFT);
/*
* If the proc is on this cpu already, lower the cost by how much
* it has been running and an estimate of its footprint.

View file

@ -1,4 +1,4 @@
/* $OpenBSD: kern_time.c,v 1.163 2023/02/15 10:07:50 claudio Exp $ */
/* $OpenBSD: kern_time.c,v 1.164 2023/08/05 20:07:55 cheloha Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@ -35,6 +35,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/clockintr.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
#include <sys/proc.h>
@ -43,6 +44,7 @@
#include <sys/stdint.h>
#include <sys/pledge.h>
#include <sys/task.h>
#include <sys/time.h>
#include <sys/timeout.h>
#include <sys/timetc.h>
@ -52,6 +54,7 @@
#include <dev/clock_subr.h>
int itimerfix(struct itimerval *);
void process_reset_itimer_flag(struct process *);
/*
* Time of day and interval timer support.
@ -551,6 +554,10 @@ setitimer(int which, const struct itimerval *itv, struct itimerval *olditv)
timeout_del(&pr->ps_realit_to);
}
*itimer = its;
if (which == ITIMER_VIRTUAL || which == ITIMER_PROF) {
process_reset_itimer_flag(pr);
need_resched(curcpu());
}
}
if (which == ITIMER_REAL)
@ -729,49 +736,72 @@ itimerfix(struct itimerval *itv)
}
/*
* Decrement an interval timer by the given number of nanoseconds.
* Decrement an interval timer by the given duration.
* If the timer expires and it is periodic then reload it. When reloading
* the timer we subtract any overrun from the next period so that the timer
* does not drift.
*/
int
itimerdecr(struct itimerspec *itp, long nsec)
itimerdecr(struct itimerspec *itp, const struct timespec *decrement)
{
struct timespec decrement;
NSEC_TO_TIMESPEC(nsec, &decrement);
mtx_enter(&itimer_mtx);
/*
* Double-check that the timer is enabled. A different thread
* in setitimer(2) may have disabled it while we were entering
* the mutex.
*/
if (!timespecisset(&itp->it_value)) {
mtx_leave(&itimer_mtx);
timespecsub(&itp->it_value, decrement, &itp->it_value);
if (itp->it_value.tv_sec >= 0 && timespecisset(&itp->it_value))
return (1);
}
/*
* The timer is enabled. Update and reload it as needed.
*/
timespecsub(&itp->it_value, &decrement, &itp->it_value);
if (itp->it_value.tv_sec >= 0 && timespecisset(&itp->it_value)) {
mtx_leave(&itimer_mtx);
return (1);
}
if (!timespecisset(&itp->it_interval)) {
timespecclear(&itp->it_value);
mtx_leave(&itimer_mtx);
return (0);
}
while (itp->it_value.tv_sec < 0 || !timespecisset(&itp->it_value))
timespecadd(&itp->it_value, &itp->it_interval, &itp->it_value);
mtx_leave(&itimer_mtx);
return (0);
}
void
itimer_update(struct clockintr *cl, void *cf)
{
struct timespec elapsed;
uint64_t nsecs;
struct clockframe *frame = cf;
struct proc *p = curproc;
struct process *pr;
if (p == NULL || ISSET(p->p_flag, P_SYSTEM | P_WEXIT))
return;
pr = p->p_p;
if (!ISSET(pr->ps_flags, PS_ITIMER))
return;
nsecs = clockintr_advance(cl, hardclock_period) * hardclock_period;
NSEC_TO_TIMESPEC(nsecs, &elapsed);
mtx_enter(&itimer_mtx);
if (CLKF_USERMODE(frame) &&
timespecisset(&pr->ps_timer[ITIMER_VIRTUAL].it_value) &&
itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], &elapsed) == 0) {
process_reset_itimer_flag(pr);
atomic_setbits_int(&p->p_flag, P_ALRMPEND);
need_proftick(p);
}
if (timespecisset(&pr->ps_timer[ITIMER_PROF].it_value) &&
itimerdecr(&pr->ps_timer[ITIMER_PROF], &elapsed) == 0) {
process_reset_itimer_flag(pr);
atomic_setbits_int(&p->p_flag, P_PROFPEND);
need_proftick(p);
}
mtx_leave(&itimer_mtx);
}
void
process_reset_itimer_flag(struct process *ps)
{
if (timespecisset(&ps->ps_timer[ITIMER_VIRTUAL].it_value) ||
timespecisset(&ps->ps_timer[ITIMER_PROF].it_value))
atomic_setbits_int(&ps->ps_flags, PS_ITIMER);
else
atomic_clearbits_int(&ps->ps_flags, PS_ITIMER);
}
struct mutex ratecheck_mtx = MUTEX_INITIALIZER(IPL_HIGH);
/*

View file

@ -1,4 +1,4 @@
/* $OpenBSD: sched_bsd.c,v 1.78 2023/07/25 18:16:19 cheloha Exp $ */
/* $OpenBSD: sched_bsd.c,v 1.79 2023/08/05 20:07:55 cheloha Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*-
@ -350,7 +350,11 @@ mi_switch(void)
/* add the time counts for this thread to the process's total */
tuagg_unlocked(pr, p);
/* Stop the profclock if it's running. */
/* Stop any optional clock interrupts. */
if (ISSET(spc->spc_schedflags, SPCF_ITIMER)) {
atomic_clearbits_int(&spc->spc_schedflags, SPCF_ITIMER);
clockintr_cancel(spc->spc_itimer);
}
if (ISSET(spc->spc_schedflags, SPCF_PROFCLOCK)) {
atomic_clearbits_int(&spc->spc_schedflags, SPCF_PROFCLOCK);
clockintr_cancel(spc->spc_profclock);
@ -400,7 +404,13 @@ mi_switch(void)
*/
KASSERT(p->p_cpu == curcpu());
/* Start the profclock if profil(2) is enabled. */
/* Start any optional clock interrupts needed by the thread. */
if (ISSET(p->p_p->ps_flags, PS_ITIMER)) {
atomic_setbits_int(&p->p_cpu->ci_schedstate.spc_schedflags,
SPCF_ITIMER);
clockintr_advance(p->p_cpu->ci_schedstate.spc_itimer,
hardclock_period);
}
if (ISSET(p->p_p->ps_flags, PS_PROFIL)) {
atomic_setbits_int(&p->p_cpu->ci_schedstate.spc_schedflags,
SPCF_PROFCLOCK);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_socket.c,v 1.306 2023/07/22 14:30:39 mvs Exp $ */
/* $OpenBSD: uipc_socket.c,v 1.307 2023/08/03 09:49:08 mvs Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@ -1789,12 +1789,12 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
{
int error = 0;
soassertlocked(so);
if (level != SOL_SOCKET) {
if (so->so_proto->pr_ctloutput) {
solock(so);
error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
level, optname, m);
sounlock(so);
return (error);
}
error = ENOPROTOOPT;
@ -1813,9 +1813,16 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
mtod(m, struct linger *)->l_linger < 0 ||
mtod(m, struct linger *)->l_linger > SHRT_MAX)
return (EINVAL);
so->so_linger = mtod(m, struct linger *)->l_linger;
/* FALLTHROUGH */
solock(so);
so->so_linger = mtod(m, struct linger *)->l_linger;
if (*mtod(m, int *))
so->so_options |= optname;
else
so->so_options &= ~optname;
sounlock(so);
break;
case SO_BINDANY:
case SO_DEBUG:
case SO_KEEPALIVE:
@ -1828,12 +1835,15 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
case SO_ZEROIZE:
if (m == NULL || m->m_len < sizeof (int))
return (EINVAL);
solock(so);
if (*mtod(m, int *))
so->so_options |= optname;
else
so->so_options &= ~optname;
break;
sounlock(so);
break;
case SO_DONTROUTE:
if (m == NULL || m->m_len < sizeof (int))
return (EINVAL);
@ -1853,23 +1863,32 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
cnt = *mtod(m, int *);
if ((long)cnt <= 0)
cnt = 1;
switch (optname) {
solock(so);
switch (optname) {
case SO_SNDBUF:
if (so->so_snd.sb_state & SS_CANTSENDMORE)
return (EINVAL);
if (so->so_snd.sb_state & SS_CANTSENDMORE) {
error = EINVAL;
break;
}
if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
sbreserve(so, &so->so_snd, cnt))
return (ENOBUFS);
sbreserve(so, &so->so_snd, cnt)) {
error = ENOBUFS;
break;
}
so->so_snd.sb_wat = cnt;
break;
case SO_RCVBUF:
if (so->so_rcv.sb_state & SS_CANTRCVMORE)
return (EINVAL);
if (so->so_rcv.sb_state & SS_CANTRCVMORE) {
error = EINVAL;
break;
}
if (sbcheckreserve(cnt, so->so_rcv.sb_wat) ||
sbreserve(so, &so->so_rcv, cnt))
return (ENOBUFS);
sbreserve(so, &so->so_rcv, cnt)) {
error = ENOBUFS;
break;
}
so->so_rcv.sb_wat = cnt;
break;
@ -1884,6 +1903,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
so->so_rcv.sb_hiwat : cnt;
break;
}
sounlock(so);
break;
}
@ -1903,8 +1923,9 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
return (EDOM);
if (nsecs == 0)
nsecs = INFSLP;
switch (optname) {
solock(so);
switch (optname) {
case SO_SNDTIMEO:
so->so_snd.sb_timeo_nsecs = nsecs;
break;
@ -1912,6 +1933,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
so->so_rcv.sb_timeo_nsecs = nsecs;
break;
}
sounlock(so);
break;
}
@ -1923,19 +1945,20 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
so->so_proto->pr_domain;
level = dom->dom_protosw->pr_protocol;
solock(so);
error = (*so->so_proto->pr_ctloutput)
(PRCO_SETOPT, so, level, optname, m);
return (error);
}
error = ENOPROTOOPT;
sounlock(so);
} else
error = ENOPROTOOPT;
break;
#ifdef SOCKET_SPLICE
case SO_SPLICE:
solock(so);
if (m == NULL) {
error = sosplice(so, -1, 0, NULL);
} else if (m->m_len < sizeof(int)) {
return (EINVAL);
error = EINVAL;
} else if (m->m_len < sizeof(struct splice)) {
error = sosplice(so, *mtod(m, int *), 0, NULL);
} else {
@ -1944,6 +1967,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
mtod(m, struct splice *)->sp_max,
&mtod(m, struct splice *)->sp_idle);
}
sounlock(so);
break;
#endif /* SOCKET_SPLICE */
@ -1951,10 +1975,6 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
error = ENOPROTOOPT;
break;
}
if (error == 0 && so->so_proto->pr_ctloutput) {
(*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
level, optname, m);
}
}
return (error);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_syscalls.c,v 1.212 2023/02/10 14:34:17 visa Exp $ */
/* $OpenBSD: uipc_syscalls.c,v 1.213 2023/08/03 09:49:08 mvs Exp $ */
/* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
/*
@ -1232,9 +1232,7 @@ sys_setsockopt(struct proc *p, void *v, register_t *retval)
m->m_len = SCARG(uap, valsize);
}
so = fp->f_data;
solock(so);
error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
sounlock(so);
bad:
m_freem(m);
FRELE(fp, p);