The net_stack_driver now uses a reference count to determine when to unload the core. This way the core is not unloaded to early and we don't need to work around the unload by opening ourselfs.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12922 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2005-06-01 17:40:28 +00:00
parent 317121e102
commit e89253271b

View File

@ -32,7 +32,7 @@
#endif
// Force the driver to stay loaded in memory
#define STAY_LOADED 0
#define STAY_LOADED 0
/*
* Local definitions
@ -139,7 +139,8 @@ device_hooks g_net_stack_driver_hooks =
NULL /* ->writev entry point */
};
struct core_module_info * core = NULL;
struct core_module_info *g_core = NULL;
uint32 g_core_reference_count = 0;
#if STAY_LOADED
int g_stay_loaded_fd = -1;
@ -194,20 +195,21 @@ _EXPORT status_t init_hardware(void)
_EXPORT status_t init_driver(void)
{
// only get the core module if we don't have it loaded already
if (!core) {
if (!g_core) {
int rv = 0;
rv = get_module(NET_CORE_MODULE_NAME, (module_info **) &core);
rv = get_module(NET_CORE_MODULE_NAME, (module_info **) &g_core);
if (rv < 0) {
TRACE((LOGID ERR "init_driver: Argh, can't load " NET_CORE_MODULE_NAME " module: %d\n", rv));
return rv;
}
TRACE((LOGID "init_driver: built %s %s, core = %p\n", __DATE__, __TIME__, core));
TRACE((LOGID "init_driver: built %s %s, core = %p\n", __DATE__, __TIME__, g_core));
// start the network stack!
core->start();
g_core->start();
}
g_core_reference_count++;
return B_OK;
}
@ -219,14 +221,14 @@ _EXPORT status_t init_driver(void)
_EXPORT void uninit_driver(void)
{
TRACE((LOGID "uninit_driver\n"));
if (core) {
#if STAY_LOADED
g_core_reference_count--;
if (g_core && g_core_reference_count == 0) {
// shutdown the network stack
core->stop();
#endif
g_core->stop();
put_module(NET_CORE_MODULE_NAME);
core = NULL;
g_core = NULL;
};
}
@ -295,7 +297,7 @@ static status_t net_stack_close(void *cookie)
rv = B_ERROR;
if (nsc->socket) {
// if a socket was opened on this fd, close it now.
rv = core->socket_close(nsc->socket);
rv = g_core->socket_close(nsc->socket);
nsc->socket = NULL;
}
@ -345,9 +347,9 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
case NET_STACK_SOCKET: {
// okay, now try to open a real socket behind this fd/net_stack_cookie pair
err = core->socket_init(&nsc->socket);
err = g_core->socket_init(&nsc->socket);
if (err == 0)
err = core->socket_create(nsc->socket, args->u.socket.family, args->u.socket.type, args->u.socket.proto);
err = g_core->socket_create(nsc->socket, args->u.socket.family, args->u.socket.type, args->u.socket.proto);
// TODO: This is where the open flags need to be addressed
return err;
}
@ -361,24 +363,24 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
return B_OK;
}
case NET_STACK_CONTROL_NET_MODULE: {
return core->control_net_module(args->u.control.name, args->u.control.op,
return g_core->control_net_module(args->u.control.name, args->u.control.op,
args->u.control.data, args->u.control.length);
}
};
} else {
switch (op) {
case NET_STACK_CONNECT:
return core->socket_connect(nsc->socket, (caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
return g_core->socket_connect(nsc->socket, (caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
case NET_STACK_SHUTDOWN:
return core->socket_shutdown(nsc->socket, args->u.integer);
return g_core->socket_shutdown(nsc->socket, args->u.integer);
case NET_STACK_BIND:
return core->socket_bind(nsc->socket, (caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
return g_core->socket_bind(nsc->socket, (caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
case NET_STACK_LISTEN:
// backlog to set
return core->socket_listen(nsc->socket, args->u.integer);
return g_core->socket_listen(nsc->socket, args->u.integer);
case NET_STACK_ACCEPT: {
/* args->u.accept.cookie == net_stack_cookie of the already opened fd
@ -386,7 +388,7 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
*/
net_stack_cookie *ansc = args->u.accept.cookie;
return core->socket_accept(nsc->socket, &ansc->socket, (void *)args->u.accept.addr, &args->u.accept.addrlen);
return g_core->socket_accept(nsc->socket, &ansc->socket, (void *)args->u.accept.addr, &args->u.accept.addrlen);
}
case NET_STACK_SEND:
// TODO: flags gets ignored here...
@ -400,7 +402,7 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
struct msghdr * mh = (struct msghdr *) data;
int retsize;
err = core->socket_recv(nsc->socket, mh, (caddr_t)&mh->msg_namelen,
err = g_core->socket_recv(nsc->socket, mh, (caddr_t)&mh->msg_namelen,
&retsize);
if (err == 0)
return retsize;
@ -410,41 +412,41 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
struct msghdr * mh = (struct msghdr *) data;
int retsize;
err = core->socket_send(nsc->socket, mh, mh->msg_flags,
err = g_core->socket_send(nsc->socket, mh, mh->msg_flags,
&retsize);
if (err == 0)
return retsize;
return err;
}
case NET_STACK_SYSCTL:
return core->net_sysctl(args->u.sysctl.name, args->u.sysctl.namelen,
return g_core->net_sysctl(args->u.sysctl.name, args->u.sysctl.namelen,
args->u.sysctl.oldp, args->u.sysctl.oldlenp,
args->u.sysctl.newp, args->u.sysctl.newlen);
case NET_STACK_GETSOCKOPT:
return core->socket_getsockopt(nsc->socket, args->u.sockopt.level, args->u.sockopt.option,
return g_core->socket_getsockopt(nsc->socket, args->u.sockopt.level, args->u.sockopt.option,
args->u.sockopt.optval, (size_t *) &args->u.sockopt.optlen);
case NET_STACK_SETSOCKOPT:
return core->socket_setsockopt(nsc->socket, args->u.sockopt.level, args->u.sockopt.option,
return g_core->socket_setsockopt(nsc->socket, args->u.sockopt.level, args->u.sockopt.option,
(const void *) args->u.sockopt.optval, args->u.sockopt.optlen);
case NET_STACK_GETSOCKNAME:
return core->socket_getsockname(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen);
return g_core->socket_getsockname(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen);
case NET_STACK_GETPEERNAME:
return core->socket_getpeername(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen);
return g_core->socket_getpeername(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen);
case B_SET_BLOCKING_IO: {
int off = false;
nsc->open_flags &= ~O_NONBLOCK;
return core->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &off);
return g_core->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &off);
}
case B_SET_NONBLOCKING_IO: {
int on = true;
nsc->open_flags |= O_NONBLOCK;
return core->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &on);
return g_core->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &on);
}
case NET_STACK_SELECT:
@ -459,7 +461,7 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
default:
if (nsc->socket)
// pass any unhandled opcode to the stack
return core->socket_ioctl(nsc->socket, op, data);
return g_core->socket_ioctl(nsc->socket, op, data);
return B_BAD_VALUE;
};
};
@ -492,7 +494,7 @@ static status_t net_stack_read(void *cookie,
iov.iov_base = buffer;
iov.iov_len = *readlen;
error = core->socket_readv(nsc->socket, &iov, &flags);
error = g_core->socket_readv(nsc->socket, &iov, &flags);
*readlen = error;
return error;
}
@ -524,7 +526,7 @@ static status_t net_stack_write(void *cookie,
#endif
if (*writelen >= strlen(STOP_CMD) &&
strncmp(buffer, STOP_CMD, strlen(STOP_CMD)) == 0)
return core->stop();
return g_core->stop();
return B_BAD_VALUE;
};
@ -532,7 +534,7 @@ static status_t net_stack_write(void *cookie,
iov.iov_base = (void*)buffer;
iov.iov_len = *writelen;
error = core->socket_writev(nsc->socket, &iov, flags);
error = g_core->socket_writev(nsc->socket, &iov, flags);
*writelen = error;
return error;
}
@ -580,7 +582,7 @@ static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsy
release_sem(nsc->selecters_lock);
// start (or continue) to monitor for socket event
return core->socket_set_event_callback(nsc->socket, on_socket_event, nsc, event);
return g_core->socket_set_event_callback(nsc->socket, on_socket_event, nsc, event);
}
@ -628,7 +630,7 @@ static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync)
if (nsc->selecters == NULL)
// selecters list is empty: no need to monitor socket events anymore
core->socket_set_event_callback(nsc->socket, NULL, NULL, event);
g_core->socket_set_event_callback(nsc->socket, NULL, NULL, event);
// unlock the selecters list
return release_sem(nsc->selecters_lock);