linux_stop_machine.c revision 1.1
11.1Sriastrad/*	$NetBSD: linux_stop_machine.c,v 1.1 2021/12/19 01:34:57 riastradh Exp $	*/
21.1Sriastrad
31.1Sriastrad/*-
41.1Sriastrad * Copyright (c) 2018 The NetBSD Foundation, Inc.
51.1Sriastrad * All rights reserved.
61.1Sriastrad *
71.1Sriastrad * This code is derived from software contributed to The NetBSD Foundation
81.1Sriastrad * by Taylor R. Campbell.
91.1Sriastrad *
101.1Sriastrad * Redistribution and use in source and binary forms, with or without
111.1Sriastrad * modification, are permitted provided that the following conditions
121.1Sriastrad * are met:
131.1Sriastrad * 1. Redistributions of source code must retain the above copyright
141.1Sriastrad *    notice, this list of conditions and the following disclaimer.
151.1Sriastrad * 2. Redistributions in binary form must reproduce the above copyright
161.1Sriastrad *    notice, this list of conditions and the following disclaimer in the
171.1Sriastrad *    documentation and/or other materials provided with the distribution.
181.1Sriastrad *
191.1Sriastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Sriastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Sriastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Sriastrad * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Sriastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Sriastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Sriastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Sriastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Sriastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Sriastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Sriastrad * POSSIBILITY OF SUCH DAMAGE.
301.1Sriastrad */
311.1Sriastrad
321.1Sriastrad#include <sys/cdefs.h>
331.1Sriastrad__KERNEL_RCSID(0, "$NetBSD: linux_stop_machine.c,v 1.1 2021/12/19 01:34:57 riastradh Exp $");
341.1Sriastrad
351.1Sriastrad#include <sys/atomic.h>
361.1Sriastrad#include <sys/intr.h>
371.1Sriastrad#include <sys/lock.h>
381.1Sriastrad#include <sys/systm.h>
391.1Sriastrad#include <sys/xcall.h>
401.1Sriastrad
411.1Sriastrad#include <linux/stop_machine.h>
421.1Sriastrad
431.1Sriastradstruct stop_machine {
441.1Sriastrad	int			(*callback)(void *);
451.1Sriastrad	void			*cookie;
461.1Sriastrad	volatile unsigned	ncpu;
471.1Sriastrad	volatile bool		done;
481.1Sriastrad};
491.1Sriastrad
501.1Sriastradstatic void
511.1Sriastradstop_machine_xcall(void *a, void *b)
521.1Sriastrad{
531.1Sriastrad	struct stop_machine *S = a;
541.1Sriastrad	int s;
551.1Sriastrad
561.1Sriastrad	/* Block all activity on this CPU.  */
571.1Sriastrad	s = splhigh();
581.1Sriastrad
591.1Sriastrad	/* Note that we're ready, and see whether we're the chosen one.  */
601.1Sriastrad	if (atomic_dec_uint_nv(&S->ncpu) != 0) {
611.1Sriastrad		/* Not the chosen one.  Wait until done.  */
621.1Sriastrad		while (!S->done)
631.1Sriastrad			SPINLOCK_BACKOFF_HOOK;
641.1Sriastrad		goto out;
651.1Sriastrad	}
661.1Sriastrad
671.1Sriastrad	/* It's time.  Call the callback.  */
681.1Sriastrad	S->callback(S->cookie);
691.1Sriastrad
701.1Sriastrad	/* Notify everyone else that we're done.  */
711.1Sriastrad	S->done = true;
721.1Sriastrad
731.1Sriastrad	/* Allow activity again.  */
741.1Sriastradout:	splx(s);
751.1Sriastrad}
761.1Sriastrad
771.1Sriastradvoid
781.1Sriastradstop_machine(int (*callback)(void *), void *cookie, const struct kcpuset *cpus)
791.1Sriastrad{
801.1Sriastrad	struct stop_machine stop, *S = &stop;
811.1Sriastrad
821.1Sriastrad	KASSERT(cpus == NULL);	/* not implemented */
831.1Sriastrad
841.1Sriastrad	S->callback = callback;
851.1Sriastrad	S->cookie = cookie;
861.1Sriastrad	S->ncpu = ncpu;		/* XXX cpu hotplug */
871.1Sriastrad	S->done = false;
881.1Sriastrad
891.1Sriastrad	xc_wait(xc_broadcast(0, stop_machine_xcall, &S, NULL));
901.1Sriastrad}
91