xref: /freebsd/lib/libsys/rfork_thread_gen.c (revision c1be185e3fb9afd6743683a8f5a43b9c364ab529)
1*c1be185eSKonstantin Belousov /*-
2*c1be185eSKonstantin Belousov  * SPDX-License-Identifier: BSD-2-Clause
3*c1be185eSKonstantin Belousov  *
4*c1be185eSKonstantin Belousov  * Copyright 2026 The FreeBSD Foundation
5*c1be185eSKonstantin Belousov  *
6*c1be185eSKonstantin Belousov  * This software were developed by
7*c1be185eSKonstantin Belousov  * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
8*c1be185eSKonstantin Belousov  * the FreeBSD Foundation.
9*c1be185eSKonstantin Belousov  */
10*c1be185eSKonstantin Belousov 
11*c1be185eSKonstantin Belousov #include <errno.h>
12*c1be185eSKonstantin Belousov #include <unistd.h>
13*c1be185eSKonstantin Belousov 
14*c1be185eSKonstantin Belousov pid_t
rfork_thread(int flags,void * stack_addr,int (* start_fn)(void *),void * arg)15*c1be185eSKonstantin Belousov rfork_thread(int flags, void *stack_addr, int (*start_fn)(void *), void *arg)
16*c1be185eSKonstantin Belousov {
17*c1be185eSKonstantin Belousov 	pid_t res;
18*c1be185eSKonstantin Belousov 	int ret;
19*c1be185eSKonstantin Belousov 
20*c1be185eSKonstantin Belousov 	/*
21*c1be185eSKonstantin Belousov 	 * Generic implementation cannot switch stacks.  Only
22*c1be185eSKonstantin Belousov 	 * architecture-specific code knows how to do it.  Require
23*c1be185eSKonstantin Belousov 	 * that caller knows that, and refuse to do operate if the
24*c1be185eSKonstantin Belousov 	 * stack was supplied.
25*c1be185eSKonstantin Belousov 	 *
26*c1be185eSKonstantin Belousov 	 * Note that implementations that do switch stack, would fault
27*c1be185eSKonstantin Belousov 	 * immediately if the passed stack is NULL.  They do not need to
28*c1be185eSKonstantin Belousov 	 * specifically check for the NULL stack value.
29*c1be185eSKonstantin Belousov 	 */
30*c1be185eSKonstantin Belousov 	if (stack_addr != NULL) {
31*c1be185eSKonstantin Belousov 		errno = EOPNOTSUPP;
32*c1be185eSKonstantin Belousov 		return (-1);
33*c1be185eSKonstantin Belousov 	}
34*c1be185eSKonstantin Belousov 	res = rfork(flags);
35*c1be185eSKonstantin Belousov 	if (res == 0) {
36*c1be185eSKonstantin Belousov 		ret = start_fn(arg);
37*c1be185eSKonstantin Belousov 		_exit(ret);
38*c1be185eSKonstantin Belousov 	}
39*c1be185eSKonstantin Belousov 	return (res);
40*c1be185eSKonstantin Belousov }
41