resource.c 3.47 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* resource.c
 *
 * External resources associated with a connection, for instance
 * processes and ports. Used to kill or release the resource in
 * question when the connection dies.
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen's avatar
J.H.M. Dassen committed
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Niels Möller's avatar
Niels Möller committed
26
27
28
29
30
31
32
 */

#include "resource.h"

#include "werror.h"
#include "xalloc.h"

33
34
#include <assert.h>

Niels Möller's avatar
Niels Möller committed
35
/* Prototypes */
36

Niels Möller's avatar
Niels Möller committed
37
38
void dont_free_live_resource(int alive);

39
#define GABA_DEFINE
Niels Möller's avatar
Niels Möller committed
40
#include "resource.h.x"
41
#undef GABA_DEFINE
Niels Möller's avatar
Niels Möller committed
42

43
44
45
46
47
48
49
50
/* Forward declarations */

struct resource_node;

void do_mark_resources(struct resource_node **q,
		       void (*mark)(struct lsh_object *o));

void do_free_resources(struct resource_node **q);
Niels Möller's avatar
Niels Möller committed
51

52
53
54
55
#include "resource.c.x"


/* Sanity check */
Niels Möller's avatar
Niels Möller committed
56
57
58
void dont_free_live_resource(int alive)
{
  if (alive)
59
60
    fatal("dont_free_live_resource: "
	  "About to garbage collect a live resource!\n");
Niels Möller's avatar
Niels Möller committed
61
62
}

63
64
65
66
67
/* The behaviour of a resource list is somewhat similar to
 * a weak list. Nodes that are dead are unlinked automatically,
 * so that they can be garbage collected. */

struct resource_node
Niels Möller's avatar
Niels Möller committed
68
{
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  struct resource_node *next;
  struct resource *resource;
};

/* GABA:
   (class
     (name concrete_resource_list)
     (super resource_list)
     (vars
       (q indirect-special "struct resource_node *"
                           do_mark_resources do_free_resources)))
*/

/* Loop over the resources, mark the living and unlink the dead. */
void do_mark_resources(struct resource_node **q,
		       void (*mark)(struct lsh_object *o))
{
  struct resource_node *n;
  
  while ( (n = *q) )
    {
      if (n->resource->alive)
	{
	  mark(&n->resource->super);
	  q = &n->next;
	}
      else
	{
	  *q = n->next;
	  lsh_space_free(n);
	}
    }
Niels Möller's avatar
Niels Möller committed
101
102
}

103
104
/* Free the list. */
void do_free_resources(struct resource_node **q)
Niels Möller's avatar
Niels Möller committed
105
{
106
107
108
  struct resource_node *n;

  for (n = *q; n; )
109
    {
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
      struct resource_node *old = n;
      n = n->next;
      lsh_space_free(old);
    }
}


static void
do_remember_resource(struct resource_list *s,
		     struct resource *resource)
{
  CAST(concrete_resource_list, self, s);
  struct resource_node *n;

  assert(self->super.super.alive);
  NEW_SPACE(n);

  n->resource = resource;
  n->next = self->q;
  self->q = n;
}

static void do_kill_all(struct resource *s)
{
  CAST(concrete_resource_list, self, s);
  struct resource_node *n;

  for (n = self->q; n; )
    {
      CAST_SUBTYPE(resource, r, n->resource);
       struct resource_node *old = n;

142
      KILL_RESOURCE(r);
143
144
145
      n = n->next;

      lsh_space_free(old);
146
    }
147
148
  self->q = NULL;
  self->super.super.alive = 0;
Niels Möller's avatar
Niels Möller committed
149
150
151
152
}
  
struct resource_list *empty_resource_list(void)
{
153
154
155
  NEW(concrete_resource_list, self);
  self->super.super.kill = do_kill_all;
  self->super.super.alive = 1;
Niels Möller's avatar
Niels Möller committed
156

157
158
159
  self->super.remember = do_remember_resource;
  
  self->q = NULL;
Niels Möller's avatar
Niels Möller committed
160

161
  return &self->super;
Niels Möller's avatar
Niels Möller committed
162
}