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
 	int ( * register_image ) ( struct image *image );
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
  * Terminate download
67
  * Terminate download
55
  *
68
  *
63
 	xfer_nullify ( &downloader->xfer );
76
 	xfer_nullify ( &downloader->xfer );
64
 
77
 
65
 	/* Free resources and close interfaces */
78
 	/* Free resources and close interfaces */
66
-	image_put ( downloader->image );
67
 	xfer_close ( &downloader->xfer, rc );
79
 	xfer_close ( &downloader->xfer, rc );
68
 	job_done ( &downloader->job, rc );
80
 	job_done ( &downloader->job, rc );
69
-
70
-	/* Drop reference to self */
71
-	ref_put ( &downloader->refcnt );
72
 }
81
 }
73
 
82
 
74
 /**
83
 /**
267
 	if ( ! downloader )
276
 	if ( ! downloader )
268
 		return -ENOMEM;
277
 		return -ENOMEM;
269
 	memset ( downloader, 0, sizeof ( *downloader ) );
278
 	memset ( downloader, 0, sizeof ( *downloader ) );
279
+	downloader->refcnt.free = downloader_free;
270
 	job_init ( &downloader->job, &downloader_job_operations,
280
 	job_init ( &downloader->job, &downloader_job_operations,
271
 		   &downloader->refcnt );
281
 		   &downloader->refcnt );
272
 	xfer_init ( &downloader->xfer, &downloader_xfer_operations,
282
 	xfer_init ( &downloader->xfer, &downloader_xfer_operations,
279
 			   uri_string ) ) != 0 )
289
 			   uri_string ) ) != 0 )
280
 		goto err;
290
 		goto err;
281
 
291
 
282
-	/* Attach parent interface and return */
292
+	/* Attach parent interface, mortalise self, and return */
283
 	job_plug_plug ( &downloader->job, job );
293
 	job_plug_plug ( &downloader->job, job );
294
+	ref_put ( &downloader->refcnt );
284
 	return 0;
295
 	return 0;
285
 
296
 
286
  err:
297
  err:
287
 	downloader_finished ( downloader, rc );
298
 	downloader_finished ( downloader, rc );
299
+	ref_put ( &downloader->refcnt );
288
 	return rc;
300
 	return rc;
289
 }
301
 }

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

22
 static void hw_finished ( struct hw *hw, int rc ) {
22
 static void hw_finished ( struct hw *hw, int rc ) {
23
 	xfer_nullify ( &hw->xfer );
23
 	xfer_nullify ( &hw->xfer );
24
 	xfer_close ( &hw->xfer, rc );
24
 	xfer_close ( &hw->xfer, rc );
25
-	ref_put ( &hw->refcnt );
26
 }
25
 }
27
 
26
 
28
 static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
27
 static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
31
 	hw_finished ( hw, rc );
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
 	struct hw *hw = container_of ( xfer, struct hw, xfer );
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
 static struct xfer_interface_operations hw_xfer_operations = {
43
 static struct xfer_interface_operations hw_xfer_operations = {
52
 static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
52
 static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
53
 	struct hw *hw;
53
 	struct hw *hw;
54
 
54
 
55
+	/* Allocate and initialise structure */
55
 	hw = malloc ( sizeof ( *hw ) );
56
 	hw = malloc ( sizeof ( *hw ) );
56
 	if ( ! hw )
57
 	if ( ! hw )
57
 		return -ENOMEM;
58
 		return -ENOMEM;
58
 	memset ( hw, 0, sizeof ( *hw ) );
59
 	memset ( hw, 0, sizeof ( *hw ) );
59
 	xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt );
60
 	xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt );
60
 
61
 
62
+	/* Attach parent interface, mortalise self, and return */
61
 	xfer_plug_plug ( &hw->xfer, xfer );
63
 	xfer_plug_plug ( &hw->xfer, xfer );
64
+	ref_put ( &hw->refcnt );
62
 	return 0;
65
 	return 0;
63
 }
66
 }
64
 
67
 

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

27
  */
27
  */
28
 
28
 
29
 void job_done ( struct job_interface *job, int rc ) {
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
 	dest->op->done ( dest, rc );
32
 	dest->op->done ( dest, rc );
33
 	job_unplug ( job );
33
 	job_unplug ( job );
34
+	job_put ( dest );
34
 }
35
 }
35
 
36
 
36
 /****************************************************************************
37
 /****************************************************************************

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

33
  * @v rc		Reason for close
33
  * @v rc		Reason for close
34
  */
34
  */
35
 void xfer_close ( struct xfer_interface *xfer, int rc ) {
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
 	dest->op->close ( dest, rc );
38
 	dest->op->close ( dest, rc );
39
 	xfer_unplug ( xfer );
39
 	xfer_unplug ( xfer );
40
+	xfer_put ( dest );
40
 }
41
 }
41
 
42
 
42
 /**
43
 /**
48
  * @ret rc		Return status code
49
  * @ret rc		Return status code
49
  */
50
  */
50
 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
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
  */
86
  */
83
 int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
87
 int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
84
 		   size_t len ) {
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
  * @ret rc		Return status code
113
  * @ret rc		Return status code
107
  */
114
  */
108
 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
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
  * @ret iobuf		I/O buffer
129
  * @ret iobuf		I/O buffer
120
  */
130
  */
121
 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
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
  * @ret rc		Return status code
145
  * @ret rc		Return status code
133
  */
146
  */
134
 int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
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
  */
162
  */
147
 int xfer_deliver_raw ( struct xfer_interface *xfer,
163
 int xfer_deliver_raw ( struct xfer_interface *xfer,
148
 		       const void *data, size_t len ) {
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
  * @v intf		Interface
34
  * @v intf		Interface
35
  * @ret intf		Interface
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
 	ref_get ( intf->refcnt );
39
 	ref_get ( intf->refcnt );
39
 	return intf;
40
 	return intf;
40
 }
41
 }
44
  *
45
  *
45
  * @v intf		Interface
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
 	ref_put ( intf->refcnt );
50
 	ref_put ( intf->refcnt );
49
 }
51
 }
50
 
52
 

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

104
 }
104
 }
105
 
105
 
106
 /**
106
 /**
107
- * Get destination job control interface
107
+ * Get reference to destination job control interface
108
  *
108
  *
109
  * @v job		Job control interface
109
  * @v job		Job control interface
110
  * @ret dest		Destination interface
110
  * @ret dest		Destination interface
111
  */
111
  */
112
 static inline __attribute__ (( always_inline )) struct job_interface *
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
 }
173
 }
174
 
174
 
175
 /**
175
 /**
176
- * Get destination data transfer interface
176
+ * Get reference to destination data transfer interface
177
  *
177
  *
178
  * @v xfer		Data transfer interface
178
  * @v xfer		Data transfer interface
179
  * @ret dest		Destination interface
179
  * @ret dest		Destination interface
180
  */
180
  */
181
 static inline __attribute__ (( always_inline )) struct xfer_interface *
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
  * @v xfer		Data transfer interface
199
  * @v xfer		Data transfer interface
190
  * @v dest		New destination interface
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
 	plug ( &xfer->intf, &dest->intf );
204
 	plug ( &xfer->intf, &dest->intf );
195
 }
205
 }
196
 
206
 
200
  * @v a			Data transfer interface A
210
  * @v a			Data transfer interface A
201
  * @v b			Data transfer interface B
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
 	plug_plug ( &a->intf, &b->intf );
215
 	plug_plug ( &a->intf, &b->intf );
206
 }
216
 }
207
 
217
 
210
  *
220
  *
211
  * @v xfer		Data transfer interface
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
 	plug ( &xfer->intf, &null_xfer.intf );
225
 	plug ( &xfer->intf, &null_xfer.intf );
215
 }
226
 }
216
 
227
 

Loading…
Cancel
Save