summaryrefslogtreecommitdiff
path: root/console
diff options
context:
space:
mode:
Diffstat (limited to 'console')
-rw-r--r--console/console.c64
1 files changed, 37 insertions, 27 deletions
diff --git a/console/console.c b/console/console.c
index 57ae8133..9c5869dd 100644
--- a/console/console.c
+++ b/console/console.c
@@ -415,47 +415,51 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type)
/* Node management. */
-/* Node NP has no more references; free all its associated
- storage. */
+/* We need to drop the soft references on NP. */
void
-netfs_node_norefs (struct node *np)
+netfs_try_dropping_softrefs (struct node *np)
{
vcons_t vcons = np->nn->vcons;
+ int release = FALSE;
- /* The root node does never go away. */
- assert (!np->nn->cons && np->nn->vcons);
-
- /* Avoid deadlock. */
- pthread_spin_unlock (&netfs_node_refcnt_lock);
-
- /* Find the back reference to ourself in the virtual console
- structure, and delete it. */
pthread_mutex_lock (&vcons->lock);
- pthread_spin_lock (&netfs_node_refcnt_lock);
- if (np->references)
+ if (np == vcons->dir_node)
{
- /* Someone else got a reference while we were attempting to go
- away. This can happen in netfs_attempt_lookup. In this
- case, just unlock the node and do nothing else. */
- pthread_mutex_unlock (&vcons->lock);
- pthread_mutex_unlock (&np->lock);
- return;
+ release = TRUE;
+ vcons->dir_node = 0;
}
- if (np == vcons->dir_node)
- vcons->dir_node = 0;
else if (np == vcons->cons_node)
- vcons->cons_node = 0;
+ {
+ release = TRUE;
+ vcons->cons_node = 0;
+ }
else if (np == vcons->disp_node)
- vcons->disp_node = 0;
- else
{
- assert (np == vcons->inpt_node);
+ release = TRUE;
+ vcons->disp_node = 0;
+ }
+ else if (np == vcons->inpt_node)
+ {
+ release = TRUE;
vcons->inpt_node = 0;
}
+ if (release)
+ netfs_nrele_light (np);
pthread_mutex_unlock (&vcons->lock);
/* Release our reference. */
- vcons_release (vcons);
+ if (release)
+ vcons_release (vcons);
+
+}
+
+/* Node NP has no more references; free all its associated
+ storage. */
+void
+netfs_node_norefs (struct node *np)
+{
+ /* The root node does never go away. */
+ assert (!np->nn->cons && np->nn->vcons);
free (np->nn);
free (np);
@@ -634,7 +638,10 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir,
the virtual console. */
err = new_node (node, vcons, VCONS_NODE_DIR);
if (!err)
- vcons->dir_node = *node;
+ {
+ vcons->dir_node = *node;
+ netfs_nref_light (*node);
+ }
else
release_vcons = 1;
}
@@ -663,6 +670,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir,
if (!err)
{
vcons->cons_node = *node;
+ netfs_nref_light (*node);
ref_vcons = 1;
}
}
@@ -682,6 +690,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir,
if (!err)
{
vcons->disp_node = *node;
+ netfs_nref_light (*node);
ref_vcons = 1;
}
}
@@ -701,6 +710,7 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir,
if (!err)
{
vcons->inpt_node = *node;
+ netfs_nref_light (*node);
ref_vcons = 1;
}
}