|
@@ -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
|
};
|