Просмотр исходного кода

Added async_block_progress() and default SIGUPDATE handler.

tags/v0.9.3
Michael Brown 18 лет назад
Родитель
Сommit
1a79437888
2 измененных файлов: 79 добавлений и 3 удалений
  1. 58
    3
      src/core/async.c
  2. 21
    0
      src/include/gpxe/async.h

+ 58
- 3
src/core/async.c Просмотреть файл

@@ -153,6 +153,28 @@ static void async_ignore_sigchld ( struct async *async, enum signal signal ) {
153 153
 	assert ( waited_aid >= 0 );
154 154
 }
155 155
 
156
+/**
157
+ * SIGUPDATE 'ignore' handler
158
+ *
159
+ * @v async		Asynchronous operation
160
+ * @v signal		Signal received
161
+ */
162
+static void async_ignore_sigupdate ( struct async *async,
163
+				     enum signal signal ) {
164
+	struct async *child;
165
+
166
+	assert ( async != NULL );
167
+	assert ( signal == SIGUPDATE );
168
+
169
+	async_signal_children ( async, signal );
170
+	async->completed = 0;
171
+	async->total = 0;
172
+	list_for_each_entry ( child, &async->children, siblings ) {
173
+		async->completed += child->completed;
174
+		async->total += child->total;
175
+	}
176
+}
177
+
156 178
 /**
157 179
  * 'Ignore' signal handler
158 180
  *
@@ -170,8 +192,10 @@ void async_ignore_signal ( struct async *async, enum signal signal ) {
170 192
 	case SIGCHLD:
171 193
 		async_ignore_sigchld ( async, signal );
172 194
 		break;
173
-	case SIGKILL:
174 195
 	case SIGUPDATE:
196
+		async_ignore_sigupdate ( async, signal );
197
+		break;
198
+	case SIGKILL:
175 199
 	default:
176 200
 		/* Nothing to do */
177 201
 		break;
@@ -391,6 +415,35 @@ aid_t async_wait ( struct async *async, int *rc, int block ) {
391 415
 	}
392 416
 }
393 417
 
418
+/**
419
+ * Wait for any child asynchronous operation to complete, with progress bar
420
+ * 
421
+ * @v child		Child asynchronous operation
422
+ * @v rc		Child exit status to fill in, or NULL
423
+ * @ret aid		Asynchronous operation ID, or -1 on error
424
+ */
425
+aid_t async_wait_progress ( struct async *async, int *rc ) {
426
+	struct async *child;
427
+	long last_progress = -1;
428
+	long progress;
429
+	aid_t child_aid;
430
+
431
+	do {
432
+		step();
433
+		async_signal ( async, SIGUPDATE );
434
+		if ( async->total ) {
435
+			progress = ( async->completed / (async->total / 100) );
436
+			if ( progress != last_progress )
437
+				printf ( "\rProgress: %d%%", progress );
438
+			last_progress = progress;
439
+		}
440
+		child_aid = async_wait ( async, rc, 0 );
441
+	} while ( *rc == -EINPROGRESS );
442
+
443
+	printf ( "\n" );
444
+	return child_aid;
445
+}
446
+
394 447
 /**
395 448
  * Default asynchronous operations
396 449
  *
@@ -400,7 +453,8 @@ aid_t async_wait ( struct async *async, int *rc, int block ) {
400 453
  */
401 454
 struct async_operations default_async_operations = {
402 455
 	.signal = {
403
-		[SIGCHLD] = SIG_IGN,
456
+		[SIGCHLD]	= SIG_IGN,
457
+		[SIGUPDATE]	= SIG_IGN,
404 458
 	},
405 459
 };
406 460
 
@@ -414,6 +468,7 @@ struct async_operations default_async_operations = {
414 468
  */
415 469
 struct async_operations orphan_async_operations = {
416 470
 	.signal = {
417
-		[SIGCHLD] = SIG_DFL,
471
+		[SIGCHLD]	= SIG_DFL,
472
+		[SIGUPDATE]	= SIG_IGN,
418 473
 	},
419 474
 };

+ 21
- 0
src/include/gpxe/async.h Просмотреть файл

@@ -204,4 +204,25 @@ static inline aid_t async_init_orphan ( struct async *async ) {
204 204
 		rc;						\
205 205
 	} )
206 206
 
207
+/**
208
+ * Execute and block on an asynchronous operation, with progress indicator
209
+ *
210
+ * @v async_temp	Temporary asynchronous operation structure to use
211
+ * @v START		Code used to start the asynchronous operation
212
+ * @ret rc		Return status code
213
+ *
214
+ * As for async_block(), the argument START is a code snippet; it
215
+ * should initiate an asynchronous operation as a child of @c
216
+ * async_temp and return an error status code if it failed to do so
217
+ * (e.g. due to malloc() failure).
218
+ */
219
+#define async_block_progress( async_temp, START ) ( {		\
220
+		int rc;						\
221
+								\
222
+	 	async_init_orphan ( async_temp );		\
223
+		if ( ( rc = START ) == 0 )			\
224
+			async_wait_progress ( async_temp, &rc );\
225
+		rc;						\
226
+	} )
227
+
207 228
 #endif /* _GPXE_ASYNC_H */

Загрузка…
Отмена
Сохранить