xref: /netbsd-src/sys/modules/lua/lua.c (revision 97f8debd624665fdeaf9373bf4602036de3fcd85)
1*97f8debdSpgoyette /*	$NetBSD: lua.c,v 1.28 2022/03/31 19:30:17 pgoyette Exp $ */
258881ebfSmbalmer 
358881ebfSmbalmer /*
4d191c429Smbalmer  * Copyright (c) 2011 - 2017 by Marc Balmer <mbalmer@NetBSD.org>.
5ba791a5eSlneto  * Copyright (c) 2014 by Lourival Vieira Neto <lneto@NetBSD.org>.
658881ebfSmbalmer  * All rights reserved.
758881ebfSmbalmer  *
858881ebfSmbalmer  * Redistribution and use in source and binary forms, with or without
958881ebfSmbalmer  * modification, are permitted provided that the following conditions
1058881ebfSmbalmer  * are met:
1158881ebfSmbalmer  * 1. Redistributions of source code must retain the above copyright
1258881ebfSmbalmer  *    notice, this list of conditions and the following disclaimer.
1358881ebfSmbalmer  * 2. Redistributions in binary form must reproduce the above copyright
1458881ebfSmbalmer  *    notice, this list of conditions and the following disclaimer in the
1558881ebfSmbalmer  *    documentation and/or other materials provided with the distribution.
1658881ebfSmbalmer  * 3. The name of the Author may not be used to endorse or promote products
1758881ebfSmbalmer  *    derived from this software without specific prior written permission.
1858881ebfSmbalmer  *
1958881ebfSmbalmer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2058881ebfSmbalmer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2158881ebfSmbalmer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2258881ebfSmbalmer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2358881ebfSmbalmer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2458881ebfSmbalmer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2558881ebfSmbalmer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2658881ebfSmbalmer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2758881ebfSmbalmer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2858881ebfSmbalmer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2958881ebfSmbalmer  * SUCH DAMAGE.
3058881ebfSmbalmer  */
3158881ebfSmbalmer 
3258881ebfSmbalmer /* Lua device driver */
3358881ebfSmbalmer 
3458881ebfSmbalmer #include <sys/param.h>
3558881ebfSmbalmer #include <sys/fcntl.h>
3658881ebfSmbalmer #include <sys/conf.h>
3758881ebfSmbalmer #include <sys/condvar.h>
3858881ebfSmbalmer #include <sys/device.h>
3958881ebfSmbalmer #include <sys/ioctl.h>
40b345b17fSmbalmer #include <sys/kmem.h>
4158881ebfSmbalmer #include <sys/lock.h>
4258881ebfSmbalmer #include <sys/lua.h>
4358881ebfSmbalmer #include <sys/module.h>
4458881ebfSmbalmer #include <sys/mutex.h>
4558881ebfSmbalmer #include <sys/namei.h>
4658881ebfSmbalmer #include <sys/queue.h>
4758881ebfSmbalmer #include <sys/sysctl.h>
4858881ebfSmbalmer #include <sys/vnode.h>
49ba791a5eSlneto #include <sys/cpu.h>
5058881ebfSmbalmer 
5158881ebfSmbalmer #include <lauxlib.h>
5258881ebfSmbalmer 
5358881ebfSmbalmer #include "luavar.h"
5458881ebfSmbalmer 
5558881ebfSmbalmer struct lua_softc {
5658881ebfSmbalmer 	device_t		 sc_dev;
5758881ebfSmbalmer 
5858881ebfSmbalmer 	kmutex_t		 sc_lock;
5958881ebfSmbalmer 	kcondvar_t		 sc_inuse_cv;
6058881ebfSmbalmer 	bool			 sc_inuse;
6158881ebfSmbalmer 
6258881ebfSmbalmer 	/* Locking access to state queues */
6358881ebfSmbalmer 	kmutex_t		 sc_state_lock;
6458881ebfSmbalmer 	kcondvar_t		 sc_state_cv;
6558881ebfSmbalmer 	bool			 sc_state;
6658881ebfSmbalmer 
6758881ebfSmbalmer 	struct sysctllog	*sc_log;
6858881ebfSmbalmer };
6958881ebfSmbalmer 
7058881ebfSmbalmer static device_t	sc_self;
7158881ebfSmbalmer static bool	lua_autoload_on = true;
7258881ebfSmbalmer static bool	lua_require_on = true;
7358881ebfSmbalmer static bool	lua_bytecode_on = false;
7458881ebfSmbalmer static int	lua_verbose;
7558881ebfSmbalmer static int	lua_max_instr;
7658881ebfSmbalmer 
779c8bf6eeSrin static LIST_HEAD(, lua_state)	lua_states =
789c8bf6eeSrin     LIST_HEAD_INITIALIZER(lua_states);
799c8bf6eeSrin static LIST_HEAD(, lua_module)	lua_modules =
809c8bf6eeSrin     LIST_HEAD_INITIALIZER(lua_modules);
8158881ebfSmbalmer 
8258881ebfSmbalmer static int lua_match(device_t, cfdata_t, void *);
8358881ebfSmbalmer static void lua_attach(device_t, device_t, void *);
8458881ebfSmbalmer static int lua_detach(device_t, int);
8558881ebfSmbalmer static klua_State *klua_find(const char *);
8658881ebfSmbalmer static const char *lua_reader(lua_State *, void *, size_t *);
8758881ebfSmbalmer static void lua_maxcount(lua_State *, lua_Debug *);
8858881ebfSmbalmer 
8958881ebfSmbalmer static int lua_require(lua_State *);
9058881ebfSmbalmer 
9158881ebfSmbalmer CFATTACH_DECL_NEW(lua, sizeof(struct lua_softc),
9258881ebfSmbalmer 	lua_match, lua_attach, lua_detach, NULL);
9358881ebfSmbalmer 
9458881ebfSmbalmer dev_type_open(luaopen);
9558881ebfSmbalmer dev_type_close(luaclose);
9658881ebfSmbalmer dev_type_ioctl(luaioctl);
9758881ebfSmbalmer 
9858881ebfSmbalmer const struct cdevsw lua_cdevsw = {
99a68f9396Sdholland 	.d_open = luaopen,
100a68f9396Sdholland 	.d_close = luaclose,
101a68f9396Sdholland 	.d_read = noread,
102a68f9396Sdholland 	.d_write = nowrite,
103a68f9396Sdholland 	.d_ioctl = luaioctl,
104a68f9396Sdholland 	.d_stop = nostop,
105a68f9396Sdholland 	.d_tty = notty,
106a68f9396Sdholland 	.d_poll = nopoll,
107a68f9396Sdholland 	.d_mmap = nommap,
108a68f9396Sdholland 	.d_kqfilter = nokqfilter,
109f9228f42Sdholland 	.d_discard = nodiscard,
110a68f9396Sdholland 	.d_flag = D_OTHER | D_MPSAFE
11158881ebfSmbalmer };
11258881ebfSmbalmer 
11358881ebfSmbalmer struct lua_loadstate {
11458881ebfSmbalmer 	struct vnode	*vp;
11558881ebfSmbalmer 	size_t		 size;
11658881ebfSmbalmer 	off_t		 off;
11758881ebfSmbalmer };
11858881ebfSmbalmer 
11958881ebfSmbalmer extern struct cfdriver lua_cd;
12058881ebfSmbalmer 
12158881ebfSmbalmer static int
lua_match(device_t parent,cfdata_t match,void * aux)12258881ebfSmbalmer lua_match(device_t parent, cfdata_t match, void *aux)
12358881ebfSmbalmer {
12458881ebfSmbalmer 	return 1;
12558881ebfSmbalmer }
12658881ebfSmbalmer 
12758881ebfSmbalmer static void
lua_attach(device_t parent,device_t self,void * aux)12858881ebfSmbalmer lua_attach(device_t parent, device_t self, void *aux)
12958881ebfSmbalmer {
13058881ebfSmbalmer 	struct lua_softc *sc;
13158881ebfSmbalmer 	const struct sysctlnode *node;
13258881ebfSmbalmer 
13358881ebfSmbalmer 	if (sc_self)
13458881ebfSmbalmer 		return;
13558881ebfSmbalmer 
13658881ebfSmbalmer 	sc = device_private(self);
13758881ebfSmbalmer 	sc->sc_dev = self;
13858881ebfSmbalmer 	sc_self = self;
13958881ebfSmbalmer 
14058881ebfSmbalmer 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
14158881ebfSmbalmer 	cv_init(&sc->sc_inuse_cv, "luactl");
14258881ebfSmbalmer 
14358881ebfSmbalmer 	mutex_init(&sc->sc_state_lock, MUTEX_DEFAULT, IPL_VM);
14458881ebfSmbalmer 	cv_init(&sc->sc_state_cv, "luastate");
14558881ebfSmbalmer 
146b8f12c7fSmaya 	if (!pmf_device_register(self, NULL, NULL))
147b8f12c7fSmaya 		aprint_error_dev(self, "couldn't establish power handler\n");
14858881ebfSmbalmer 
14958881ebfSmbalmer 	/* Sysctl to provide some control over behaviour */
15058881ebfSmbalmer         sysctl_createv(&sc->sc_log, 0, NULL, &node,
15158881ebfSmbalmer             CTLFLAG_OWNDESC,
15258881ebfSmbalmer             CTLTYPE_NODE, "lua",
15358881ebfSmbalmer             SYSCTL_DESCR("Lua options"),
15458881ebfSmbalmer             NULL, 0, NULL, 0,
15558881ebfSmbalmer             CTL_KERN, CTL_CREATE, CTL_EOL);
15658881ebfSmbalmer 
15758881ebfSmbalmer         if (node == NULL) {
158d21ffc75Smsaitoh 		aprint_error(": can't create sysctl node\n");
15958881ebfSmbalmer                 return;
16058881ebfSmbalmer 	}
16158881ebfSmbalmer 
16258881ebfSmbalmer 	/*
16358881ebfSmbalmer 	 * XXX Some of the sysctl values must not be changed after the
16458881ebfSmbalmer 	 * securelevel has been raised.
16558881ebfSmbalmer 	 */
16658881ebfSmbalmer         sysctl_createv(&sc->sc_log, 0, &node, NULL,
16758881ebfSmbalmer             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
16858881ebfSmbalmer             CTLTYPE_BOOL, "require",
16958881ebfSmbalmer             SYSCTL_DESCR("Enable the require command"),
17058881ebfSmbalmer             NULL, 0, &lua_require_on, 0,
17158881ebfSmbalmer 	    CTL_CREATE, CTL_EOL);
17258881ebfSmbalmer 
17358881ebfSmbalmer         sysctl_createv(&sc->sc_log, 0, &node, NULL,
17458881ebfSmbalmer             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
17558881ebfSmbalmer             CTLTYPE_BOOL, "autoload",
17658881ebfSmbalmer             SYSCTL_DESCR("Enable automatic load of modules"),
17758881ebfSmbalmer             NULL, 0, &lua_autoload_on, 0,
17858881ebfSmbalmer 	    CTL_CREATE, CTL_EOL);
17958881ebfSmbalmer 
18058881ebfSmbalmer         sysctl_createv(&sc->sc_log, 0, &node, NULL,
18158881ebfSmbalmer             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
18258881ebfSmbalmer             CTLTYPE_BOOL, "bytecode",
18358881ebfSmbalmer             SYSCTL_DESCR("Enable loading of bytecode"),
18458881ebfSmbalmer             NULL, 0, &lua_bytecode_on, 0,
18558881ebfSmbalmer 	    CTL_CREATE, CTL_EOL);
18658881ebfSmbalmer 
18758881ebfSmbalmer         sysctl_createv(&sc->sc_log, 0, &node, NULL,
18858881ebfSmbalmer             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
18958881ebfSmbalmer             CTLTYPE_INT, "verbose",
19058881ebfSmbalmer             SYSCTL_DESCR("Enable verbose output"),
19158881ebfSmbalmer             NULL, 0, &lua_verbose, 0,
19258881ebfSmbalmer 	    CTL_CREATE, CTL_EOL);
19358881ebfSmbalmer 
19458881ebfSmbalmer         sysctl_createv(&sc->sc_log, 0, &node, NULL,
19558881ebfSmbalmer             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
19658881ebfSmbalmer             CTLTYPE_INT, "maxcount",
19758881ebfSmbalmer             SYSCTL_DESCR("Limit maximum instruction count"),
19858881ebfSmbalmer             NULL, 0, &lua_max_instr, 0,
19958881ebfSmbalmer 	    CTL_CREATE, CTL_EOL);
20058881ebfSmbalmer 
2014ab4902eSlneto 	aprint_normal_dev(self, "%s\n", LUA_COPYRIGHT);
20258881ebfSmbalmer }
20358881ebfSmbalmer 
20458881ebfSmbalmer static int
lua_detach(device_t self,int flags)20558881ebfSmbalmer lua_detach(device_t self, int flags)
20658881ebfSmbalmer {
20758881ebfSmbalmer 	struct lua_softc *sc;
20858881ebfSmbalmer 	struct lua_state *s;
20958881ebfSmbalmer 
21058881ebfSmbalmer 	sc = device_private(self);
21158881ebfSmbalmer 	pmf_device_deregister(self);
21258881ebfSmbalmer 
21358881ebfSmbalmer 	if (sc->sc_log != NULL) {
21458881ebfSmbalmer 		sysctl_teardown(&sc->sc_log);
21558881ebfSmbalmer 		sc->sc_log = NULL;
21658881ebfSmbalmer 	}
21758881ebfSmbalmer 
21858881ebfSmbalmer 	/* Traverse the list of states and close them */
21958881ebfSmbalmer 	while ((s = LIST_FIRST(&lua_states)) != NULL) {
22058881ebfSmbalmer 		LIST_REMOVE(s, lua_next);
22158881ebfSmbalmer 		klua_close(s->K);
22258881ebfSmbalmer 		if (lua_verbose)
22358881ebfSmbalmer 			device_printf(self, "state %s destroyed\n",
22458881ebfSmbalmer 			    s->lua_name);
225b345b17fSmbalmer 		kmem_free(s, sizeof(struct lua_state));
22658881ebfSmbalmer 	}
22758881ebfSmbalmer 	mutex_destroy(&sc->sc_lock);
22858881ebfSmbalmer 	cv_destroy(&sc->sc_inuse_cv);
22958881ebfSmbalmer 	mutex_destroy(&sc->sc_state_lock);
23058881ebfSmbalmer 	cv_destroy(&sc->sc_state_cv);
23158881ebfSmbalmer 	sc_self = NULL;
23258881ebfSmbalmer 	return 0;
23358881ebfSmbalmer }
23458881ebfSmbalmer 
23558881ebfSmbalmer int
luaopen(dev_t dev,int flag,int mode,struct lwp * l)23658881ebfSmbalmer luaopen(dev_t dev, int flag, int mode, struct lwp *l)
23758881ebfSmbalmer {
23858881ebfSmbalmer 	struct lua_softc *sc;
2393b5eeb2bSmbalmer 	int error = 0;
24058881ebfSmbalmer 
24158881ebfSmbalmer 	if (minor(dev) > 0)
24258881ebfSmbalmer 		return ENXIO;
24358881ebfSmbalmer 
24458881ebfSmbalmer 	sc = device_lookup_private(&lua_cd, minor(dev));
24558881ebfSmbalmer 	if (sc == NULL)
24658881ebfSmbalmer 		return ENXIO;
24758881ebfSmbalmer 
24858881ebfSmbalmer 	mutex_enter(&sc->sc_lock);
24958881ebfSmbalmer 	while (sc->sc_inuse == true) {
25058881ebfSmbalmer 		error = cv_wait_sig(&sc->sc_inuse_cv, &sc->sc_lock);
25158881ebfSmbalmer 		if (error)
25258881ebfSmbalmer 			break;
25358881ebfSmbalmer 	}
25458881ebfSmbalmer 	if (!error)
25558881ebfSmbalmer 		sc->sc_inuse = true;
25658881ebfSmbalmer 	mutex_exit(&sc->sc_lock);
25758881ebfSmbalmer 
25858881ebfSmbalmer 	if (error)
25958881ebfSmbalmer 		return error;
26058881ebfSmbalmer 	return 0;
26158881ebfSmbalmer }
26258881ebfSmbalmer 
26358881ebfSmbalmer int
luaclose(dev_t dev,int flag,int mode,struct lwp * l)26458881ebfSmbalmer luaclose(dev_t dev, int flag, int mode, struct lwp *l)
26558881ebfSmbalmer {
26658881ebfSmbalmer 	struct lua_softc *sc;
26758881ebfSmbalmer 
26858881ebfSmbalmer 	if (minor(dev) > 0)
26958881ebfSmbalmer 		return ENXIO;
27058881ebfSmbalmer 	sc = device_lookup_private(&lua_cd, minor(dev));
27158881ebfSmbalmer 	mutex_enter(&sc->sc_lock);
27258881ebfSmbalmer 	sc->sc_inuse = false;
27358881ebfSmbalmer 	cv_signal(&sc->sc_inuse_cv);
27458881ebfSmbalmer 	mutex_exit(&sc->sc_lock);
27558881ebfSmbalmer 	return 0;
27658881ebfSmbalmer }
27758881ebfSmbalmer 
27858881ebfSmbalmer int
luaioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)27958881ebfSmbalmer luaioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
28058881ebfSmbalmer {
28158881ebfSmbalmer 	struct lua_softc *sc;
28258881ebfSmbalmer 	struct lua_info *info;
28358881ebfSmbalmer 	struct lua_create *create;
28458881ebfSmbalmer 	struct lua_require *require;
28558881ebfSmbalmer 	struct lua_load *load;
28658881ebfSmbalmer 	struct lua_state *s;
28758881ebfSmbalmer 	struct lua_module *m;
28858881ebfSmbalmer 	kauth_cred_t cred;
289723d09ceSdholland 	struct vnode *vp;
29058881ebfSmbalmer 	struct pathbuf *pb;
29158881ebfSmbalmer 	struct vattr va;
29258881ebfSmbalmer 	struct lua_loadstate ls;
29363f6d58fSmartin 	struct lua_state_info *states;
29458881ebfSmbalmer 	int error, n;
29558881ebfSmbalmer 	klua_State *K;
29658881ebfSmbalmer 
29758881ebfSmbalmer 	sc = device_lookup_private(&lua_cd, minor(dev));
29858881ebfSmbalmer 	if (!device_is_active(sc->sc_dev))
29958881ebfSmbalmer 		return EBUSY;
30058881ebfSmbalmer 
30158881ebfSmbalmer 	switch (cmd) {
30258881ebfSmbalmer 	case LUAINFO:
30358881ebfSmbalmer 		info = data;
30458881ebfSmbalmer 		if (info->states == NULL) {
30558881ebfSmbalmer 			info->num_states = 0;
30658881ebfSmbalmer 			LIST_FOREACH(s, &lua_states, lua_next)
30758881ebfSmbalmer 				info->num_states++;
30858881ebfSmbalmer 		} else {
30958881ebfSmbalmer 			n = 0;
31058881ebfSmbalmer 			LIST_FOREACH(s, &lua_states, lua_next) {
31158881ebfSmbalmer 				if (n > info->num_states)
31258881ebfSmbalmer 					break;
31358881ebfSmbalmer 				n++;
31458881ebfSmbalmer 			}
31558881ebfSmbalmer 			info->num_states = n;
31663f6d58fSmartin 			states = kmem_alloc(sizeof(*states) * n, KM_SLEEP);
31763f6d58fSmartin 			if (copyin(info->states, states, sizeof(*states) * n)
31863f6d58fSmartin 			    == 0) {
31963f6d58fSmartin 				n = 0;
32063f6d58fSmartin 				LIST_FOREACH(s, &lua_states, lua_next) {
32163f6d58fSmartin 					if (n > info->num_states)
32263f6d58fSmartin 						break;
32363f6d58fSmartin 					strcpy(states[n].name, s->lua_name);
32463f6d58fSmartin 					strcpy(states[n].desc, s->lua_desc);
32563f6d58fSmartin 					states[n].user = s->K->ks_user;
32663f6d58fSmartin 					n++;
32763f6d58fSmartin 				}
32863f6d58fSmartin 				copyout(states, info->states,
32963f6d58fSmartin 				    sizeof(*states) * n);
33063f6d58fSmartin 				kmem_free(states, sizeof(*states) * n);
33163f6d58fSmartin 			}
33258881ebfSmbalmer 		}
33358881ebfSmbalmer 		break;
33458881ebfSmbalmer 	case LUACREATE:
33558881ebfSmbalmer 		create = data;
33658881ebfSmbalmer 
33758881ebfSmbalmer 		if (*create->name == '_') {
33858881ebfSmbalmer 			if (lua_verbose)
33958881ebfSmbalmer 				device_printf(sc->sc_dev, "names of user "
34058881ebfSmbalmer 				    "created states must not begin with '_'");
34158881ebfSmbalmer 				return ENXIO;
34258881ebfSmbalmer 		}
34358881ebfSmbalmer 		LIST_FOREACH(s, &lua_states, lua_next)
34458881ebfSmbalmer 			if (!strcmp(s->lua_name, create->name)) {
34558881ebfSmbalmer 				if (lua_verbose)
34658881ebfSmbalmer 					device_printf(sc->sc_dev,
34758881ebfSmbalmer 					    "state %s exists\n", create->name);
34858881ebfSmbalmer 				return EBUSY;
34958881ebfSmbalmer 			}
35058881ebfSmbalmer 
351ba791a5eSlneto 		K = kluaL_newstate(create->name, create->desc, IPL_NONE);
35258881ebfSmbalmer 
35358881ebfSmbalmer 		if (K == NULL)
35458881ebfSmbalmer 			return ENOMEM;
3553c246ec0Smbalmer 
3563c246ec0Smbalmer 		K->ks_user = true;
3573c246ec0Smbalmer 
35858881ebfSmbalmer 		if (lua_verbose)
35958881ebfSmbalmer 			device_printf(sc->sc_dev, "state %s created\n",
36058881ebfSmbalmer 			    create->name);
36158881ebfSmbalmer 		break;
36258881ebfSmbalmer 	case LUADESTROY:
36358881ebfSmbalmer 		create = data;
36458881ebfSmbalmer 
36558881ebfSmbalmer 		K = klua_find(create->name);
36658881ebfSmbalmer 
36758881ebfSmbalmer 		if (K != NULL && (K->ks_user == true)) {
36858881ebfSmbalmer 			klua_close(K);
36958881ebfSmbalmer 			return 0;
37058881ebfSmbalmer 		}
37158881ebfSmbalmer 		return EBUSY;
37258881ebfSmbalmer 	case LUAREQUIRE:	/* 'require' a module in a State */
37358881ebfSmbalmer 		require = data;
37458881ebfSmbalmer 		LIST_FOREACH(s, &lua_states, lua_next)
3757093afb2Ssalazar 			if (!strcmp(s->lua_name, require->state)) {
3767093afb2Ssalazar 				LIST_FOREACH(m, &s->lua_modules, mod_next)
3777093afb2Ssalazar 					if (!strcmp(m->mod_name, require->module))
3787093afb2Ssalazar 						return ENXIO;
37958881ebfSmbalmer 				LIST_FOREACH(m, &lua_modules, mod_next)
38058881ebfSmbalmer 					if (!strcmp(m->mod_name,
38158881ebfSmbalmer 					    require->module)) {
38258881ebfSmbalmer 					    	if (lua_verbose)
38358881ebfSmbalmer 						    	device_printf(
38458881ebfSmbalmer 						    	    sc->sc_dev,
38558881ebfSmbalmer 					    		    "requiring module "
38658881ebfSmbalmer 					    		    "%s to state %s\n",
38758881ebfSmbalmer 					    		    m->mod_name,
38858881ebfSmbalmer 					    		    s->lua_name);
389ba791a5eSlneto 						klua_lock(s->K);
39026258645Slneto 						luaL_requiref(
39126258645Slneto 							s->K->L,
39226258645Slneto 							m->mod_name,
39326258645Slneto 							m->open,
39426258645Slneto 							1);
395ba791a5eSlneto 						klua_unlock(s->K);
39658881ebfSmbalmer 					    	m->refcount++;
39758881ebfSmbalmer 					    	LIST_INSERT_HEAD(
39858881ebfSmbalmer 					    	    &s->lua_modules, m,
39958881ebfSmbalmer 					    	    mod_next);
40058881ebfSmbalmer 					    	return 0;
40158881ebfSmbalmer 					}
4027093afb2Ssalazar 			}
40358881ebfSmbalmer 		return ENXIO;
40458881ebfSmbalmer 	case LUALOAD:
40558881ebfSmbalmer 		load = data;
40658881ebfSmbalmer 		if (strrchr(load->path, '/') == NULL)
40758881ebfSmbalmer 			return ENXIO;
40858881ebfSmbalmer 
40958881ebfSmbalmer 		LIST_FOREACH(s, &lua_states, lua_next)
41058881ebfSmbalmer 			if (!strcmp(s->lua_name, load->state)) {
41158881ebfSmbalmer 				if (lua_verbose)
41258881ebfSmbalmer 					device_printf(sc->sc_dev,
41358881ebfSmbalmer 					    "loading %s into state %s\n",
41458881ebfSmbalmer 					    load->path, s->lua_name);
41558881ebfSmbalmer 				cred = kauth_cred_get();
41658881ebfSmbalmer 				pb = pathbuf_create(load->path);
41758881ebfSmbalmer 				if (pb == NULL)
41858881ebfSmbalmer 					return ENOMEM;
419723d09ceSdholland 				error = vn_open(NULL, pb, NOCHROOT, FREAD, 0,
420723d09ceSdholland 				    &vp, NULL, NULL);
421e67dab8dSriastradh 				pathbuf_destroy(pb);
42258881ebfSmbalmer 				if (error) {
42358881ebfSmbalmer 					if (lua_verbose)
42458881ebfSmbalmer 						device_printf(sc->sc_dev,
42558881ebfSmbalmer 						    "error vn_open %d\n",
42658881ebfSmbalmer 						    error);
42758881ebfSmbalmer 					return error;
42858881ebfSmbalmer 				}
429723d09ceSdholland 				error = VOP_GETATTR(vp, &va,
43058881ebfSmbalmer 				    kauth_cred_get());
43158881ebfSmbalmer 				if (error) {
432723d09ceSdholland 					VOP_UNLOCK(vp);
433723d09ceSdholland 					vn_close(vp, FREAD,
43458881ebfSmbalmer 					    kauth_cred_get());
43558881ebfSmbalmer 					if (lua_verbose)
43658881ebfSmbalmer 						device_printf(sc->sc_dev,
43758881ebfSmbalmer 						    "erro VOP_GETATTR %d\n",
43858881ebfSmbalmer 						    error);
43958881ebfSmbalmer 					return error;
44058881ebfSmbalmer 				}
44158881ebfSmbalmer 				if (va.va_type != VREG) {
442723d09ceSdholland 					VOP_UNLOCK(vp);
443723d09ceSdholland 					vn_close(vp, FREAD,
44458881ebfSmbalmer 					    kauth_cred_get());
44558881ebfSmbalmer 					return EINVAL;
44658881ebfSmbalmer 				}
447723d09ceSdholland 				ls.vp = vp;
44858881ebfSmbalmer 				ls.off = 0L;
44958881ebfSmbalmer 				ls.size = va.va_size;
450723d09ceSdholland 				VOP_UNLOCK(vp);
451ba791a5eSlneto 				klua_lock(s->K);
45258881ebfSmbalmer 				error = lua_load(s->K->L, lua_reader, &ls,
4534ab4902eSlneto 				    strrchr(load->path, '/') + 1, "bt");
454723d09ceSdholland 				vn_close(vp, FREAD, cred);
45558881ebfSmbalmer 				switch (error) {
45658881ebfSmbalmer 				case 0:	/* no error */
45758881ebfSmbalmer 					break;
45858881ebfSmbalmer 				case LUA_ERRSYNTAX:
45958881ebfSmbalmer 					if (lua_verbose)
46058881ebfSmbalmer 						device_printf(sc->sc_dev,
46158881ebfSmbalmer 						    "syntax error\n");
462ba791a5eSlneto 					klua_unlock(s->K);
46358881ebfSmbalmer 					return EINVAL;
46458881ebfSmbalmer 				case LUA_ERRMEM:
46558881ebfSmbalmer 					if (lua_verbose)
46658881ebfSmbalmer 						device_printf(sc->sc_dev,
46758881ebfSmbalmer 						    "memory error\n");
468ba791a5eSlneto 					klua_unlock(s->K);
46958881ebfSmbalmer 					return ENOMEM;
47058881ebfSmbalmer 				default:
47158881ebfSmbalmer 					if (lua_verbose)
47258881ebfSmbalmer 						device_printf(sc->sc_dev,
47358881ebfSmbalmer 						    "load error %d: %s\n",
47458881ebfSmbalmer 						    error,
47558881ebfSmbalmer 						    lua_tostring(s->K->L, -1));
476ba791a5eSlneto 					klua_unlock(s->K);
47758881ebfSmbalmer 					return EINVAL;
47858881ebfSmbalmer 				}
47958881ebfSmbalmer 				if (lua_max_instr > 0)
48058881ebfSmbalmer 					lua_sethook(s->K->L, lua_maxcount,
48158881ebfSmbalmer 					    LUA_MASKCOUNT, lua_max_instr);
48258881ebfSmbalmer 				error = lua_pcall(s->K->L, 0, LUA_MULTRET, 0);
48358881ebfSmbalmer 				if (error) {
48458881ebfSmbalmer 					if (lua_verbose) {
48558881ebfSmbalmer 						device_printf(sc->sc_dev,
48658881ebfSmbalmer 						    "execution error: %s\n",
48758881ebfSmbalmer 						    lua_tostring(s->K->L, -1));
48858881ebfSmbalmer 					}
489ba791a5eSlneto 					klua_unlock(s->K);
49058881ebfSmbalmer 					return EINVAL;
49158881ebfSmbalmer 				}
492ba791a5eSlneto 				klua_unlock(s->K);
49358881ebfSmbalmer 				return 0;
49458881ebfSmbalmer 			}
49558881ebfSmbalmer 		return ENXIO;
49658881ebfSmbalmer 	}
49758881ebfSmbalmer 	return 0;
49858881ebfSmbalmer }
49958881ebfSmbalmer 
50058881ebfSmbalmer static int
lua_require(lua_State * L)50158881ebfSmbalmer lua_require(lua_State *L)
50258881ebfSmbalmer {
50358881ebfSmbalmer 	struct lua_state *s;
50458881ebfSmbalmer 	struct lua_module *m, *md;
50558881ebfSmbalmer 	const char *module;
50658881ebfSmbalmer 	char name[MAXPATHLEN];
50758881ebfSmbalmer 
50858881ebfSmbalmer 	module = lua_tostring(L, -1);
50958881ebfSmbalmer 	md = NULL;
51058881ebfSmbalmer 	LIST_FOREACH(m, &lua_modules, mod_next)
51158881ebfSmbalmer 		if (!strcmp(m->mod_name, module)) {
51258881ebfSmbalmer 			md = m;
51358881ebfSmbalmer 			break;
51458881ebfSmbalmer 		}
51558881ebfSmbalmer 
51658881ebfSmbalmer 	if (md == NULL && lua_autoload_on && strchr(module, '/') == NULL) {
51758881ebfSmbalmer 		snprintf(name, sizeof name, "lua%s", module);
51858881ebfSmbalmer 		if (lua_verbose)
51958881ebfSmbalmer 			device_printf(sc_self, "autoload %s\n", name);
520c1f5fe0aSmbalmer 		module_autoload(name, MODULE_CLASS_MISC);
52158881ebfSmbalmer 		LIST_FOREACH(m, &lua_modules, mod_next)
52258881ebfSmbalmer 			if (!strcmp(m->mod_name, module)) {
52358881ebfSmbalmer 				md = m;
52458881ebfSmbalmer 				break;
52558881ebfSmbalmer 			}
52658881ebfSmbalmer 	}
52758881ebfSmbalmer 
52858881ebfSmbalmer 	if (md != NULL)
52958881ebfSmbalmer 		LIST_FOREACH(s, &lua_states, lua_next)
53058881ebfSmbalmer 			if (s->K->L == L) {
53158881ebfSmbalmer 				if (lua_verbose)
53258881ebfSmbalmer 					device_printf(sc_self,
53358881ebfSmbalmer 					    "require module %s\n",
53458881ebfSmbalmer 					    md->mod_name);
53526258645Slneto 				luaL_requiref(L, md->mod_name, md->open, 0);
53626258645Slneto 
537934d80f7Smbalmer 				LIST_FOREACH(m, &s->lua_modules, mod_next)
538934d80f7Smbalmer 					if (m == md)
539934d80f7Smbalmer 						return 1;
540934d80f7Smbalmer 
54158881ebfSmbalmer 				md->refcount++;
54258881ebfSmbalmer 				LIST_INSERT_HEAD(&s->lua_modules, md, mod_next);
5434ab4902eSlneto 				return 1;
54458881ebfSmbalmer 			}
54558881ebfSmbalmer 
54658881ebfSmbalmer 	lua_pushstring(L, "module not found");
54758881ebfSmbalmer 	return lua_error(L);
54858881ebfSmbalmer }
54958881ebfSmbalmer 
550ba791a5eSlneto typedef struct {
551ba791a5eSlneto 	size_t size;
55246895156Srin } alloc_header_t;
553ba791a5eSlneto 
554ba791a5eSlneto static void *
lua_alloc(void * ud,void * ptr,size_t osize,size_t nsize)55558881ebfSmbalmer lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
55658881ebfSmbalmer {
557ba791a5eSlneto 	void *nptr = NULL;
558b345b17fSmbalmer 
55946895156Srin 	/*
56046895156Srin 	 * Make sure that buffers allocated by lua_alloc() are aligned to
56146895156Srin 	 * 8-byte boundaries as done by kmem_alloc(9).
56246895156Srin 	 */
56346895156Srin 	const size_t hdr_size = roundup(sizeof(alloc_header_t), 8);
564ba791a5eSlneto 	alloc_header_t *hdr = (alloc_header_t *) ((char *) ptr - hdr_size);
565ba791a5eSlneto 
566ba791a5eSlneto 	if (nsize == 0) { /* freeing */
56758881ebfSmbalmer 		if (ptr != NULL)
568ba791a5eSlneto 			kmem_intr_free(hdr, hdr->size);
569ba791a5eSlneto 	} else if (ptr != NULL && nsize <= hdr->size - hdr_size) /* shrinking */
570ba791a5eSlneto 		return ptr; /* don't need to reallocate */
571ba791a5eSlneto 	else { /* creating or expanding */
572ba791a5eSlneto 		km_flag_t sleep = cpu_intr_p() || cpu_softintr_p() ?
573ba791a5eSlneto 			KM_NOSLEEP : KM_SLEEP;
574ba791a5eSlneto 
575ba791a5eSlneto 		size_t alloc_size = nsize + hdr_size;
576ba791a5eSlneto 		alloc_header_t *nhdr = kmem_intr_alloc(alloc_size, sleep);
577ba791a5eSlneto 		if (nhdr == NULL) /* failed to allocate */
578ba791a5eSlneto 			return NULL;
579ba791a5eSlneto 
580ba791a5eSlneto 		nhdr->size = alloc_size;
581ba791a5eSlneto 		nptr = (void *) ((char *) nhdr + hdr_size);
582ba791a5eSlneto 
583ba791a5eSlneto 		if (ptr != NULL) { /* expanding */
584ba791a5eSlneto 			memcpy(nptr, ptr, osize);
585ba791a5eSlneto 			kmem_intr_free(hdr, hdr->size);
586b345b17fSmbalmer 		}
587b345b17fSmbalmer 	}
588b345b17fSmbalmer 	return nptr;
58958881ebfSmbalmer }
59058881ebfSmbalmer 
59158881ebfSmbalmer static const char *
lua_reader(lua_State * L,void * data,size_t * size)59258881ebfSmbalmer lua_reader(lua_State *L, void *data, size_t *size)
59358881ebfSmbalmer {
59458881ebfSmbalmer 	struct lua_loadstate *ls;
59558881ebfSmbalmer 	static char buf[1024];
59658881ebfSmbalmer 	size_t rsiz;
59758881ebfSmbalmer 
59858881ebfSmbalmer 	ls = data;
59958881ebfSmbalmer 	if (ls->size < sizeof(buf))
60058881ebfSmbalmer 		rsiz = ls->size;
60158881ebfSmbalmer 	else
60258881ebfSmbalmer 		rsiz = sizeof(buf);
60358881ebfSmbalmer 	vn_rdwr(UIO_READ, ls->vp, buf, rsiz, ls->off, UIO_SYSSPACE,
60458881ebfSmbalmer 	    0, curlwp->l_cred, NULL, curlwp);
60558881ebfSmbalmer 	if (ls->off == 0L && lua_bytecode_on == false && buf[0] == 0x1b) {
60658881ebfSmbalmer 		*size = 0L;
60758881ebfSmbalmer 		lua_pushstring(L, "loading of bytecode is not allowed");
60858881ebfSmbalmer 		lua_error(L);
60958881ebfSmbalmer 		return NULL;
61058881ebfSmbalmer 	} else {
61158881ebfSmbalmer 		*size = rsiz;
61258881ebfSmbalmer 		ls->off += *size;
61358881ebfSmbalmer 		ls->size -= *size;
61458881ebfSmbalmer 	}
61558881ebfSmbalmer 	return buf;
61658881ebfSmbalmer }
61758881ebfSmbalmer 
61858881ebfSmbalmer static void
lua_maxcount(lua_State * L,lua_Debug * d)61958881ebfSmbalmer lua_maxcount(lua_State *L, lua_Debug *d)
62058881ebfSmbalmer {
62158881ebfSmbalmer 	lua_pushstring(L, "maximum instruction count exceeded");
62258881ebfSmbalmer 	lua_error(L);
62358881ebfSmbalmer }
62458881ebfSmbalmer 
62558881ebfSmbalmer int
klua_mod_register(const char * name,lua_CFunction open)6264e28dab9Slneto klua_mod_register(const char *name, lua_CFunction open)
62758881ebfSmbalmer {
62858881ebfSmbalmer 	struct lua_module *m;
62958881ebfSmbalmer 
63058881ebfSmbalmer 	LIST_FOREACH(m, &lua_modules, mod_next)
63158881ebfSmbalmer 		if (!strcmp(m->mod_name, name))
63258881ebfSmbalmer 			return EBUSY;
633b345b17fSmbalmer 	m = kmem_zalloc(sizeof(struct lua_module), KM_SLEEP);
63458881ebfSmbalmer 	strlcpy(m->mod_name, name, LUA_MAX_MODNAME);
63558881ebfSmbalmer 	m->open = open;
63658881ebfSmbalmer 	m->refcount = 0;
63758881ebfSmbalmer 	LIST_INSERT_HEAD(&lua_modules, m, mod_next);
63858881ebfSmbalmer 	if (lua_verbose)
63958881ebfSmbalmer 		device_printf(sc_self, "registered lua module %s\n", name);
64058881ebfSmbalmer 	return 0;
64158881ebfSmbalmer }
64258881ebfSmbalmer 
64358881ebfSmbalmer int
klua_mod_unregister(const char * name)6444e28dab9Slneto klua_mod_unregister(const char *name)
64558881ebfSmbalmer {
64658881ebfSmbalmer 	struct lua_module *m;
64758881ebfSmbalmer 
64858881ebfSmbalmer 	LIST_FOREACH(m, &lua_modules, mod_next)
64958881ebfSmbalmer 		if (!strcmp(m->mod_name, name)) {
65058881ebfSmbalmer 			if (m->refcount == 0) {
65158881ebfSmbalmer 				LIST_REMOVE(m, mod_next);
652b345b17fSmbalmer 				kmem_free(m, sizeof(struct lua_module));
65358881ebfSmbalmer 				if (lua_verbose)
65458881ebfSmbalmer 					device_printf(sc_self,
65558881ebfSmbalmer 					    "unregistered lua module %s\n",
65658881ebfSmbalmer 					    name);
65758881ebfSmbalmer 				return 0;
65858881ebfSmbalmer 			} else
65958881ebfSmbalmer 				return EBUSY;
66058881ebfSmbalmer 		}
66158881ebfSmbalmer 	return 0;
66258881ebfSmbalmer }
66358881ebfSmbalmer 
66458881ebfSmbalmer klua_State *
klua_newstate(lua_Alloc f,void * ud,const char * name,const char * desc,int ipl)665ba791a5eSlneto klua_newstate(lua_Alloc f, void *ud, const char *name, const char *desc,
666ba791a5eSlneto     int ipl)
66758881ebfSmbalmer {
66858881ebfSmbalmer 	klua_State *K;
66958881ebfSmbalmer 	struct lua_state *s;
67058881ebfSmbalmer 	struct lua_softc *sc;
6713b5eeb2bSmbalmer 	int error = 0;
67258881ebfSmbalmer 
673b345b17fSmbalmer 	s = kmem_zalloc(sizeof(struct lua_state), KM_SLEEP);
67458881ebfSmbalmer 	sc = device_private(sc_self);
67558881ebfSmbalmer 	mutex_enter(&sc->sc_state_lock);
67658881ebfSmbalmer 	while (sc->sc_state == true) {
67758881ebfSmbalmer 		error = cv_wait_sig(&sc->sc_state_cv, &sc->sc_state_lock);
67858881ebfSmbalmer 		if (error)
67958881ebfSmbalmer 			break;
68058881ebfSmbalmer 	}
68158881ebfSmbalmer 	if (!error)
68258881ebfSmbalmer 		sc->sc_state = true;
68358881ebfSmbalmer 	mutex_exit(&sc->sc_state_lock);
68458881ebfSmbalmer 
6854bb71db0Schristos 	if (error) {
6864bb71db0Schristos 		kmem_free(s, sizeof(struct lua_state));
68758881ebfSmbalmer 		return NULL;
6884bb71db0Schristos 	}
68958881ebfSmbalmer 
690b345b17fSmbalmer 	K = kmem_zalloc(sizeof(klua_State), KM_SLEEP);
69158881ebfSmbalmer 	K->L = lua_newstate(f, ud);
69258881ebfSmbalmer 	K->ks_user = false;
69358881ebfSmbalmer 	if (K->L == NULL) {
694b345b17fSmbalmer 		kmem_free(K, sizeof(klua_State));
69558881ebfSmbalmer 		K = NULL;
69658881ebfSmbalmer 		goto finish;
69758881ebfSmbalmer 	}
69858881ebfSmbalmer 
69958881ebfSmbalmer 	strlcpy(s->lua_name, name, MAX_LUA_NAME);
70058881ebfSmbalmer 	strlcpy(s->lua_desc, desc, MAX_LUA_DESC);
70158881ebfSmbalmer 	s->K = K;
70258881ebfSmbalmer 
70358881ebfSmbalmer 	if (lua_require_on || lua_autoload_on) {
70458881ebfSmbalmer 		lua_pushcfunction(K->L, lua_require);
70558881ebfSmbalmer 		lua_setglobal(K->L, "require");
70658881ebfSmbalmer 	}
70758881ebfSmbalmer 	LIST_INSERT_HEAD(&lua_states, s, lua_next);
70858881ebfSmbalmer 
709ba791a5eSlneto 	mutex_init(&K->ks_lock, MUTEX_DEFAULT, ipl);
71058881ebfSmbalmer 
71158881ebfSmbalmer finish:
71258881ebfSmbalmer 	mutex_enter(&sc->sc_state_lock);
71358881ebfSmbalmer 	sc->sc_state = false;
71458881ebfSmbalmer 	cv_signal(&sc->sc_state_cv);
71558881ebfSmbalmer 	mutex_exit(&sc->sc_state_lock);
71658881ebfSmbalmer 	return K;
71758881ebfSmbalmer }
71858881ebfSmbalmer 
719ba791a5eSlneto inline klua_State *
kluaL_newstate(const char * name,const char * desc,int ipl)720ba791a5eSlneto kluaL_newstate(const char *name, const char *desc, int ipl)
721ba791a5eSlneto {
722ba791a5eSlneto 	return klua_newstate(lua_alloc, NULL, name, desc, ipl);
723ba791a5eSlneto }
724ba791a5eSlneto 
72558881ebfSmbalmer void
klua_close(klua_State * K)72658881ebfSmbalmer klua_close(klua_State *K)
72758881ebfSmbalmer {
7289c8bf6eeSrin 	struct lua_state *s, *ns;
72958881ebfSmbalmer 	struct lua_softc *sc;
73058881ebfSmbalmer 	struct lua_module *m;
7313b5eeb2bSmbalmer 	int error = 0;
73258881ebfSmbalmer 
733433f0999Smbalmer 	/* XXX consider registering a handler instead of a fixed name. */
73458881ebfSmbalmer 	lua_getglobal(K->L, "onClose");
73558881ebfSmbalmer 	if (lua_isfunction(K->L, -1))
73658881ebfSmbalmer 		lua_pcall(K->L, -1, 0, 0);
73758881ebfSmbalmer 
73858881ebfSmbalmer 	sc = device_private(sc_self);
73958881ebfSmbalmer 	mutex_enter(&sc->sc_state_lock);
74058881ebfSmbalmer 	while (sc->sc_state == true) {
74158881ebfSmbalmer 		error = cv_wait_sig(&sc->sc_state_cv, &sc->sc_state_lock);
74258881ebfSmbalmer 		if (error)
74358881ebfSmbalmer 			break;
74458881ebfSmbalmer 	}
74558881ebfSmbalmer 	if (!error)
74658881ebfSmbalmer 		sc->sc_state = true;
74758881ebfSmbalmer 	mutex_exit(&sc->sc_state_lock);
74858881ebfSmbalmer 
74958881ebfSmbalmer 	if (error)
75058881ebfSmbalmer 		return;		/* Nothing we can do... */
75158881ebfSmbalmer 
7529c8bf6eeSrin 	LIST_FOREACH_SAFE(s, &lua_states, lua_next, ns)
75358881ebfSmbalmer 		if (s->K == K) {
75458881ebfSmbalmer 			LIST_REMOVE(s, lua_next);
75558881ebfSmbalmer 			LIST_FOREACH(m, &s->lua_modules, mod_next)
75658881ebfSmbalmer 				m->refcount--;
757b345b17fSmbalmer 			kmem_free(s, sizeof(struct lua_state));
75858881ebfSmbalmer 		}
75958881ebfSmbalmer 
76058881ebfSmbalmer 	lua_close(K->L);
76158881ebfSmbalmer 	mutex_destroy(&K->ks_lock);
762b345b17fSmbalmer 	kmem_free(K, sizeof(klua_State));
76358881ebfSmbalmer 
76458881ebfSmbalmer 	mutex_enter(&sc->sc_state_lock);
76558881ebfSmbalmer 	sc->sc_state = false;
76658881ebfSmbalmer 	cv_signal(&sc->sc_state_cv);
76758881ebfSmbalmer 	mutex_exit(&sc->sc_state_lock);
76858881ebfSmbalmer }
76958881ebfSmbalmer 
77058881ebfSmbalmer static klua_State *
klua_find(const char * name)77158881ebfSmbalmer klua_find(const char *name)
77258881ebfSmbalmer {
77358881ebfSmbalmer 	struct lua_state *s;
77458881ebfSmbalmer 	struct lua_softc *sc;
77558881ebfSmbalmer 	klua_State *K;
7763b5eeb2bSmbalmer 	int error = 0;
77758881ebfSmbalmer 
77858881ebfSmbalmer 	K = NULL;
77958881ebfSmbalmer 	sc = device_private(sc_self);
78058881ebfSmbalmer 	mutex_enter(&sc->sc_state_lock);
78158881ebfSmbalmer 	while (sc->sc_state == true) {
78258881ebfSmbalmer 		error = cv_wait_sig(&sc->sc_state_cv, &sc->sc_state_lock);
78358881ebfSmbalmer 		if (error)
78458881ebfSmbalmer 			break;
78558881ebfSmbalmer 	}
78658881ebfSmbalmer 	if (!error)
78758881ebfSmbalmer 		sc->sc_state = true;
78858881ebfSmbalmer 	mutex_exit(&sc->sc_state_lock);
78958881ebfSmbalmer 
79058881ebfSmbalmer 	if (error)
79158881ebfSmbalmer 		return NULL;
79258881ebfSmbalmer 
79358881ebfSmbalmer 	LIST_FOREACH(s, &lua_states, lua_next)
79458881ebfSmbalmer 		if (!strcmp(s->lua_name, name)) {
79558881ebfSmbalmer 			K = s->K;
79658881ebfSmbalmer 			break;
79758881ebfSmbalmer 		}
79858881ebfSmbalmer 
79958881ebfSmbalmer 	mutex_enter(&sc->sc_state_lock);
80058881ebfSmbalmer 	sc->sc_state = false;
80158881ebfSmbalmer 	cv_signal(&sc->sc_state_cv);
80258881ebfSmbalmer 	mutex_exit(&sc->sc_state_lock);
80358881ebfSmbalmer 	return K;
80458881ebfSmbalmer }
80558881ebfSmbalmer 
806ba791a5eSlneto inline void
klua_lock(klua_State * K)80758881ebfSmbalmer klua_lock(klua_State *K)
80858881ebfSmbalmer {
80958881ebfSmbalmer 	mutex_enter(&K->ks_lock);
81058881ebfSmbalmer }
81158881ebfSmbalmer 
812ba791a5eSlneto inline void
klua_unlock(klua_State * K)81358881ebfSmbalmer klua_unlock(klua_State *K)
81458881ebfSmbalmer {
81558881ebfSmbalmer 	mutex_exit(&K->ks_lock);
81658881ebfSmbalmer }
81758881ebfSmbalmer 
81858881ebfSmbalmer MODULE(MODULE_CLASS_MISC, lua, NULL);
81958881ebfSmbalmer 
82058881ebfSmbalmer #ifdef _MODULE
82158881ebfSmbalmer static const struct cfiattrdata luabus_iattrdata = {
82258881ebfSmbalmer 	"luabus", 0, { { NULL, NULL, 0 },}
82358881ebfSmbalmer };
824433f0999Smbalmer 
82558881ebfSmbalmer static const struct cfiattrdata *const lua_attrs[] = {
82658881ebfSmbalmer 	&luabus_iattrdata, NULL
82758881ebfSmbalmer };
828433f0999Smbalmer 
82958881ebfSmbalmer CFDRIVER_DECL(lua, DV_DULL, lua_attrs);
83058881ebfSmbalmer extern struct cfattach lua_ca;
83158881ebfSmbalmer static int lualoc[] = {
83258881ebfSmbalmer 	-1,
83358881ebfSmbalmer 	-1,
83458881ebfSmbalmer 	-1
83558881ebfSmbalmer };
836433f0999Smbalmer 
83758881ebfSmbalmer static struct cfdata lua_cfdata[] = {
83858881ebfSmbalmer 	{
83958881ebfSmbalmer 		.cf_name = "lua",
84058881ebfSmbalmer 		.cf_atname = "lua",
84158881ebfSmbalmer 		.cf_unit = 0,
84258881ebfSmbalmer 		.cf_fstate = FSTATE_STAR,
84358881ebfSmbalmer 		.cf_loc = lualoc,
84458881ebfSmbalmer 		.cf_flags = 0,
84558881ebfSmbalmer 		.cf_pspec = NULL,
84658881ebfSmbalmer 	},
84758881ebfSmbalmer 	{ NULL, NULL, 0, FSTATE_NOTFOUND, NULL, 0, NULL }
84858881ebfSmbalmer };
84958881ebfSmbalmer #endif
85058881ebfSmbalmer 
85158881ebfSmbalmer static int
lua_modcmd(modcmd_t cmd,void * opaque)85258881ebfSmbalmer lua_modcmd(modcmd_t cmd, void *opaque)
85358881ebfSmbalmer {
85458881ebfSmbalmer #ifdef _MODULE
85558881ebfSmbalmer 	devmajor_t cmajor, bmajor;
85658881ebfSmbalmer 	int error = 0;
85758881ebfSmbalmer 
85858881ebfSmbalmer 	cmajor = bmajor = NODEVMAJOR;
85958881ebfSmbalmer #endif
86058881ebfSmbalmer 	switch (cmd) {
86158881ebfSmbalmer 	case MODULE_CMD_INIT:
86258881ebfSmbalmer #ifdef _MODULE
863*97f8debdSpgoyette 		error = devsw_attach(lua_cd.cd_name, NULL, &bmajor,
864*97f8debdSpgoyette 		    &lua_cdevsw, &cmajor);
865*97f8debdSpgoyette 		if (error) {
866*97f8debdSpgoyette 			aprint_error("%s: unable to register devsw\n",
867*97f8debdSpgoyette 			    lua_cd.cd_name);
86858881ebfSmbalmer 			return error;
869*97f8debdSpgoyette 		}
870*97f8debdSpgoyette 
871*97f8debdSpgoyette 		error = config_cfdriver_attach(&lua_cd);
872*97f8debdSpgoyette 		if (error) {
873*97f8debdSpgoyette 			devsw_detach(NULL, &lua_cdevsw);
874*97f8debdSpgoyette 			return error;
875*97f8debdSpgoyette 		}
87658881ebfSmbalmer 
87758881ebfSmbalmer 		error = config_cfattach_attach(lua_cd.cd_name,
87858881ebfSmbalmer 		    &lua_ca);
87958881ebfSmbalmer 		if (error) {
88058881ebfSmbalmer 			config_cfdriver_detach(&lua_cd);
881*97f8debdSpgoyette 			devsw_detach(NULL, &lua_cdevsw);
88258881ebfSmbalmer 			aprint_error("%s: unable to register cfattach\n",
88358881ebfSmbalmer 			    lua_cd.cd_name);
88458881ebfSmbalmer 			return error;
88558881ebfSmbalmer 		}
88658881ebfSmbalmer 		error = config_cfdata_attach(lua_cfdata, 1);
88758881ebfSmbalmer 		if (error) {
88858881ebfSmbalmer 			config_cfattach_detach(lua_cd.cd_name,
88958881ebfSmbalmer 			    &lua_ca);
89058881ebfSmbalmer 			config_cfdriver_detach(&lua_cd);
891*97f8debdSpgoyette 			devsw_detach(NULL, &lua_cdevsw);
89258881ebfSmbalmer 			aprint_error("%s: unable to register cfdata\n",
89358881ebfSmbalmer 			    lua_cd.cd_name);
89458881ebfSmbalmer 			return error;
89558881ebfSmbalmer 		}
89658881ebfSmbalmer 		config_attach_pseudo(lua_cfdata);
89758881ebfSmbalmer #endif
89858881ebfSmbalmer 		return 0;
89958881ebfSmbalmer 	case MODULE_CMD_FINI:
90058881ebfSmbalmer #ifdef _MODULE
90158881ebfSmbalmer 		error = config_cfdata_detach(lua_cfdata);
90258881ebfSmbalmer 		if (error)
90358881ebfSmbalmer 			return error;
90458881ebfSmbalmer 
90558881ebfSmbalmer 		config_cfattach_detach(lua_cd.cd_name, &lua_ca);
90658881ebfSmbalmer 		config_cfdriver_detach(&lua_cd);
90758881ebfSmbalmer 		devsw_detach(NULL, &lua_cdevsw);
90858881ebfSmbalmer #endif
90958881ebfSmbalmer 		return 0;
91058881ebfSmbalmer 	case MODULE_CMD_AUTOUNLOAD:
91158881ebfSmbalmer 		/* no auto-unload */
91258881ebfSmbalmer 		return EBUSY;
91358881ebfSmbalmer 	default:
91458881ebfSmbalmer 		return ENOTTY;
91558881ebfSmbalmer 	}
91658881ebfSmbalmer }
917