Browse Source

Do not hold self-references. This then avoids the problem of having to

ensure that we only drop our self-reference exactly once.

To maintain the guarantee that an object won't go out of scope
unexpectedly while one of its event handlers is being called, the
event-calling functions now automatically obtain and drop extra
references.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
b1755462ab
7 changed files with 96 additions and 38 deletions
  1. 17
    5
      src/core/downloader.c
  2. 9
    6
      src/core/hw.c
  3. 2
    1
      src/core/job.c
  4. 32
    13
      src/core/xfer.c
  5. 4
    2
      src/include/gpxe/interface.h
  6. 13
    3
      src/include/gpxe/job.h
  7. 19
    8
      src/include/gpxe/xfer.h

+ 17
- 5
src/core/downloader.c View File

@@ -50,6 +50,19 @@ struct downloader {
50 50
 	int ( * register_image ) ( struct image *image );
51 51
 };
52 52
 
53
+/**
54
+ * Free downloader object
55
+ *
56
+ * @v refcnt		Downloader reference counter
57
+ */
58
+static void downloader_free ( struct refcnt *refcnt ) {
59
+	struct downloader *downloader =
60
+		container_of ( refcnt, struct downloader, refcnt );
61
+
62
+	image_put ( downloader->image );
63
+	free ( downloader );
64
+}
65
+
53 66
 /**
54 67
  * Terminate download
55 68
  *
@@ -63,12 +76,8 @@ static void downloader_finished ( struct downloader *downloader, int rc ) {
63 76
 	xfer_nullify ( &downloader->xfer );
64 77
 
65 78
 	/* Free resources and close interfaces */
66
-	image_put ( downloader->image );
67 79
 	xfer_close ( &downloader->xfer, rc );
68 80
 	job_done ( &downloader->job, rc );
69
-
70
-	/* Drop reference to self */
71
-	ref_put ( &downloader->refcnt );
72 81
 }
73 82
 
74 83
 /**
@@ -267,6 +276,7 @@ int create_downloader ( struct job_interface *job, const char *uri_string,
267 276
 	if ( ! downloader )
268 277
 		return -ENOMEM;
269 278
 	memset ( downloader, 0, sizeof ( *downloader ) );
279
+	downloader->refcnt.free = downloader_free;
270 280
 	job_init ( &downloader->job, &downloader_job_operations,
271 281
 		   &downloader->refcnt );
272 282
 	xfer_init ( &downloader->xfer, &downloader_xfer_operations,
@@ -279,11 +289,13 @@ int create_downloader ( struct job_interface *job, const char *uri_string,
279 289
 			   uri_string ) ) != 0 )
280 290
 		goto err;
281 291
 
282
-	/* Attach parent interface and return */
292
+	/* Attach parent interface, mortalise self, and return */
283 293
 	job_plug_plug ( &downloader->job, job );
294
+	ref_put ( &downloader->refcnt );
284 295
 	return 0;
285 296
 
286 297
  err:
287 298
 	downloader_finished ( downloader, rc );
299
+	ref_put ( &downloader->refcnt );
288 300
 	return rc;
289 301
 }

+ 9
- 6
src/core/hw.c View File

@@ -22,7 +22,6 @@ static const char hw_msg[] = "Hello world!\n";
22 22
 static void hw_finished ( struct hw *hw, int rc ) {
23 23
 	xfer_nullify ( &hw->xfer );
24 24
 	xfer_close ( &hw->xfer, rc );
25
-	ref_put ( &hw->refcnt );
26 25
 }
27 26
 
28 27
 static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
@@ -31,13 +30,14 @@ static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
31 30
 	hw_finished ( hw, rc );
32 31
 }
33 32
 
34
-static int hw_xfer_request ( struct xfer_interface *xfer, off_t start __unused,
35
-			     int whence __unused, size_t len __unused ) {
33
+static void hw_xfer_request ( struct xfer_interface *xfer,
34
+			      off_t start __unused, int whence __unused,
35
+			      size_t len __unused ) {
36 36
 	struct hw *hw = container_of ( xfer, struct hw, xfer );
37
+	int rc;
37 38
 
38
-	xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) );
39
-	hw_finished ( hw, 0 );
40
-	return 0;
39
+	rc = xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) );
40
+	hw_finished ( hw, rc );
41 41
 }
42 42
 
43 43
 static struct xfer_interface_operations hw_xfer_operations = {
@@ -52,13 +52,16 @@ static struct xfer_interface_operations hw_xfer_operations = {
52 52
 static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
53 53
 	struct hw *hw;
54 54
 
55
+	/* Allocate and initialise structure */
55 56
 	hw = malloc ( sizeof ( *hw ) );
56 57
 	if ( ! hw )
57 58
 		return -ENOMEM;
58 59
 	memset ( hw, 0, sizeof ( *hw ) );
59 60
 	xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt );
60 61
 
62
+	/* Attach parent interface, mortalise self, and return */
61 63
 	xfer_plug_plug ( &hw->xfer, xfer );
64
+	ref_put ( &hw->refcnt );
62 65
 	return 0;
63 66
 }
64 67
 

+ 2
- 1
src/core/job.c View File

@@ -27,10 +27,11 @@
27 27
  */
28 28
 
29 29
 void job_done ( struct job_interface *job, int rc ) {
30
-	struct job_interface *dest = job_dest ( job );
30
+	struct job_interface *dest = job_get_dest ( job );
31 31
 
32 32
 	dest->op->done ( dest, rc );
33 33
 	job_unplug ( job );
34
+	job_put ( dest );
34 35
 }
35 36
 
36 37
 /****************************************************************************

+ 32
- 13
src/core/xfer.c View File

@@ -33,10 +33,11 @@
33 33
  * @v rc		Reason for close
34 34
  */
35 35
 void xfer_close ( struct xfer_interface *xfer, int rc ) {
36
-	struct xfer_interface *dest = xfer_dest ( xfer );
36
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
37 37
 
38 38
 	dest->op->close ( dest, rc );
39 39
 	xfer_unplug ( xfer );
40
+	xfer_put ( dest );
40 41
 }
41 42
 
42 43
 /**
@@ -48,9 +49,12 @@ void xfer_close ( struct xfer_interface *xfer, int rc ) {
48 49
  * @ret rc		Return status code
49 50
  */
50 51
 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
51
-	struct xfer_interface *dest = xfer_dest ( xfer );
52
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
53
+	int rc;
52 54
 
53
-	return dest->op->vredirect ( dest, type, args );
55
+	rc = dest->op->vredirect ( dest, type, args );
56
+	xfer_put ( dest );
57
+	return rc;
54 58
 }
55 59
 
56 60
 /**
@@ -82,9 +86,12 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
82 86
  */
83 87
 int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
84 88
 		   size_t len ) {
85
-	struct xfer_interface *dest = xfer_dest ( xfer );
89
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
90
+	int rc;
86 91
 
87
-	return dest->op->request ( dest, offset, whence, len );
92
+	rc = dest->op->request ( dest, offset, whence, len );
93
+	xfer_put ( dest );
94
+	return rc;
88 95
 }
89 96
 
90 97
 /**
@@ -106,9 +113,12 @@ int xfer_request_all ( struct xfer_interface *xfer ) {
106 113
  * @ret rc		Return status code
107 114
  */
108 115
 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
109
-	struct xfer_interface *dest = xfer_dest ( xfer );
116
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
117
+	int rc;
110 118
 
111
-	return dest->op->seek ( dest, offset, whence );
119
+	rc = dest->op->seek ( dest, offset, whence );
120
+	xfer_put ( dest );
121
+	return rc;
112 122
 }
113 123
 
114 124
 /**
@@ -119,9 +129,12 @@ int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
119 129
  * @ret iobuf		I/O buffer
120 130
  */
121 131
 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
122
-	struct xfer_interface *dest = xfer_dest ( xfer );
132
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
133
+	struct io_buffer *iobuf;
123 134
 
124
-	return dest->op->alloc_iob ( dest, len );
135
+	iobuf = dest->op->alloc_iob ( dest, len );
136
+	xfer_put ( dest );
137
+	return iobuf;
125 138
 }
126 139
 
127 140
 /**
@@ -132,9 +145,12 @@ struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
132 145
  * @ret rc		Return status code
133 146
  */
134 147
 int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
135
-	struct xfer_interface *dest = xfer_dest ( xfer );
148
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
149
+	int rc;
136 150
 
137
-	return dest->op->deliver_iob ( dest, iobuf );
151
+	rc = dest->op->deliver_iob ( dest, iobuf );
152
+	xfer_put ( dest );
153
+	return rc;
138 154
 }
139 155
 
140 156
 /**
@@ -146,9 +162,12 @@ int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
146 162
  */
147 163
 int xfer_deliver_raw ( struct xfer_interface *xfer,
148 164
 		       const void *data, size_t len ) {
149
-	struct xfer_interface *dest = xfer_dest ( xfer );
165
+	struct xfer_interface *dest = xfer_get_dest ( xfer );
166
+	int rc;
150 167
 
151
-	return dest->op->deliver_raw ( dest, data, len );
168
+	rc = dest->op->deliver_raw ( dest, data, len );
169
+	xfer_put ( dest );
170
+	return rc;
152 171
 }
153 172
 
154 173
 /****************************************************************************

+ 4
- 2
src/include/gpxe/interface.h View File

@@ -34,7 +34,8 @@ struct interface {
34 34
  * @v intf		Interface
35 35
  * @ret intf		Interface
36 36
  */
37
-static inline struct interface * intf_get ( struct interface *intf ) {
37
+static inline __attribute__ (( always_inline )) struct interface *
38
+intf_get ( struct interface *intf ) {
38 39
 	ref_get ( intf->refcnt );
39 40
 	return intf;
40 41
 }
@@ -44,7 +45,8 @@ static inline struct interface * intf_get ( struct interface *intf ) {
44 45
  *
45 46
  * @v intf		Interface
46 47
  */
47
-static inline void intf_put ( struct interface *intf ) {
48
+static inline __attribute__ (( always_inline )) void
49
+intf_put ( struct interface *intf ) {
48 50
 	ref_put ( intf->refcnt );
49 51
 }
50 52
 

+ 13
- 3
src/include/gpxe/job.h View File

@@ -104,14 +104,24 @@ intf_to_job ( struct interface *intf ) {
104 104
 }
105 105
 
106 106
 /**
107
- * Get destination job control interface
107
+ * Get reference to destination job control interface
108 108
  *
109 109
  * @v job		Job control interface
110 110
  * @ret dest		Destination interface
111 111
  */
112 112
 static inline __attribute__ (( always_inline )) struct job_interface *
113
-job_dest ( struct job_interface *job ) {
114
-	return intf_to_job ( job->intf.dest );
113
+job_get_dest ( struct job_interface *job ) {
114
+	return intf_to_job ( intf_get ( job->intf.dest ) );
115
+}
116
+
117
+/**
118
+ * Drop reference to job control interface
119
+ *
120
+ * @v job		Job control interface
121
+ */
122
+static inline __attribute__ (( always_inline )) void
123
+job_put ( struct job_interface *job ) {
124
+	intf_put ( &job->intf );
115 125
 }
116 126
 
117 127
 /**

+ 19
- 8
src/include/gpxe/xfer.h View File

@@ -173,14 +173,24 @@ intf_to_xfer ( struct interface *intf ) {
173 173
 }
174 174
 
175 175
 /**
176
- * Get destination data transfer interface
176
+ * Get reference to destination data transfer interface
177 177
  *
178 178
  * @v xfer		Data transfer interface
179 179
  * @ret dest		Destination interface
180 180
  */
181 181
 static inline __attribute__ (( always_inline )) struct xfer_interface *
182
-xfer_dest ( struct xfer_interface *xfer ) {
183
-	return intf_to_xfer ( xfer->intf.dest );
182
+xfer_get_dest ( struct xfer_interface *xfer ) {
183
+	return intf_to_xfer ( intf_get ( xfer->intf.dest ) );
184
+}
185
+
186
+/**
187
+ * Drop reference to data transfer interface
188
+ *
189
+ * @v xfer		Data transfer interface
190
+ */
191
+static inline __attribute__ (( always_inline )) void
192
+xfer_put ( struct xfer_interface *xfer ) {
193
+	intf_put ( &xfer->intf );
184 194
 }
185 195
 
186 196
 /**
@@ -189,8 +199,8 @@ xfer_dest ( struct xfer_interface *xfer ) {
189 199
  * @v xfer		Data transfer interface
190 200
  * @v dest		New destination interface
191 201
  */
192
-static inline void xfer_plug ( struct xfer_interface *xfer,
193
-			       struct xfer_interface *dest ) {
202
+static inline __attribute__ (( always_inline )) void
203
+xfer_plug ( struct xfer_interface *xfer, struct xfer_interface *dest ) {
194 204
 	plug ( &xfer->intf, &dest->intf );
195 205
 }
196 206
 
@@ -200,8 +210,8 @@ static inline void xfer_plug ( struct xfer_interface *xfer,
200 210
  * @v a			Data transfer interface A
201 211
  * @v b			Data transfer interface B
202 212
  */
203
-static inline void xfer_plug_plug ( struct xfer_interface *a,
204
-				    struct xfer_interface *b ) {
213
+static inline __attribute__ (( always_inline )) void
214
+xfer_plug_plug ( struct xfer_interface *a, struct xfer_interface *b ) {
205 215
 	plug_plug ( &a->intf, &b->intf );
206 216
 }
207 217
 
@@ -210,7 +220,8 @@ static inline void xfer_plug_plug ( struct xfer_interface *a,
210 220
  *
211 221
  * @v xfer		Data transfer interface
212 222
  */
213
-static inline void xfer_unplug ( struct xfer_interface *xfer ) {
223
+static inline __attribute__ (( always_inline )) void
224
+xfer_unplug ( struct xfer_interface *xfer ) {
214 225
 	plug ( &xfer->intf, &null_xfer.intf );
215 226
 }
216 227
 

Loading…
Cancel
Save