mirror of https://github.com/ipxe/ipxe.git
Added async_block_progress() and default SIGUPDATE handler.
parent
c42a384709
commit
1a79437888
|
@ -153,6 +153,28 @@ static void async_ignore_sigchld ( struct async *async, enum signal signal ) {
|
||||||
assert ( waited_aid >= 0 );
|
assert ( waited_aid >= 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SIGUPDATE 'ignore' handler
|
||||||
|
*
|
||||||
|
* @v async Asynchronous operation
|
||||||
|
* @v signal Signal received
|
||||||
|
*/
|
||||||
|
static void async_ignore_sigupdate ( struct async *async,
|
||||||
|
enum signal signal ) {
|
||||||
|
struct async *child;
|
||||||
|
|
||||||
|
assert ( async != NULL );
|
||||||
|
assert ( signal == SIGUPDATE );
|
||||||
|
|
||||||
|
async_signal_children ( async, signal );
|
||||||
|
async->completed = 0;
|
||||||
|
async->total = 0;
|
||||||
|
list_for_each_entry ( child, &async->children, siblings ) {
|
||||||
|
async->completed += child->completed;
|
||||||
|
async->total += child->total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'Ignore' signal handler
|
* 'Ignore' signal handler
|
||||||
*
|
*
|
||||||
|
@ -170,8 +192,10 @@ void async_ignore_signal ( struct async *async, enum signal signal ) {
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
async_ignore_sigchld ( async, signal );
|
async_ignore_sigchld ( async, signal );
|
||||||
break;
|
break;
|
||||||
case SIGKILL:
|
|
||||||
case SIGUPDATE:
|
case SIGUPDATE:
|
||||||
|
async_ignore_sigupdate ( async, signal );
|
||||||
|
break;
|
||||||
|
case SIGKILL:
|
||||||
default:
|
default:
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
break;
|
break;
|
||||||
|
@ -391,6 +415,35 @@ aid_t async_wait ( struct async *async, int *rc, int block ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for any child asynchronous operation to complete, with progress bar
|
||||||
|
*
|
||||||
|
* @v child Child asynchronous operation
|
||||||
|
* @v rc Child exit status to fill in, or NULL
|
||||||
|
* @ret aid Asynchronous operation ID, or -1 on error
|
||||||
|
*/
|
||||||
|
aid_t async_wait_progress ( struct async *async, int *rc ) {
|
||||||
|
struct async *child;
|
||||||
|
long last_progress = -1;
|
||||||
|
long progress;
|
||||||
|
aid_t child_aid;
|
||||||
|
|
||||||
|
do {
|
||||||
|
step();
|
||||||
|
async_signal ( async, SIGUPDATE );
|
||||||
|
if ( async->total ) {
|
||||||
|
progress = ( async->completed / (async->total / 100) );
|
||||||
|
if ( progress != last_progress )
|
||||||
|
printf ( "\rProgress: %d%%", progress );
|
||||||
|
last_progress = progress;
|
||||||
|
}
|
||||||
|
child_aid = async_wait ( async, rc, 0 );
|
||||||
|
} while ( *rc == -EINPROGRESS );
|
||||||
|
|
||||||
|
printf ( "\n" );
|
||||||
|
return child_aid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default asynchronous operations
|
* Default asynchronous operations
|
||||||
*
|
*
|
||||||
|
@ -400,7 +453,8 @@ aid_t async_wait ( struct async *async, int *rc, int block ) {
|
||||||
*/
|
*/
|
||||||
struct async_operations default_async_operations = {
|
struct async_operations default_async_operations = {
|
||||||
.signal = {
|
.signal = {
|
||||||
[SIGCHLD] = SIG_IGN,
|
[SIGCHLD] = SIG_IGN,
|
||||||
|
[SIGUPDATE] = SIG_IGN,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -414,6 +468,7 @@ struct async_operations default_async_operations = {
|
||||||
*/
|
*/
|
||||||
struct async_operations orphan_async_operations = {
|
struct async_operations orphan_async_operations = {
|
||||||
.signal = {
|
.signal = {
|
||||||
[SIGCHLD] = SIG_DFL,
|
[SIGCHLD] = SIG_DFL,
|
||||||
|
[SIGUPDATE] = SIG_IGN,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -204,4 +204,25 @@ static inline aid_t async_init_orphan ( struct async *async ) {
|
||||||
rc; \
|
rc; \
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute and block on an asynchronous operation, with progress indicator
|
||||||
|
*
|
||||||
|
* @v async_temp Temporary asynchronous operation structure to use
|
||||||
|
* @v START Code used to start the asynchronous operation
|
||||||
|
* @ret rc Return status code
|
||||||
|
*
|
||||||
|
* As for async_block(), the argument START is a code snippet; it
|
||||||
|
* should initiate an asynchronous operation as a child of @c
|
||||||
|
* async_temp and return an error status code if it failed to do so
|
||||||
|
* (e.g. due to malloc() failure).
|
||||||
|
*/
|
||||||
|
#define async_block_progress( async_temp, START ) ( { \
|
||||||
|
int rc; \
|
||||||
|
\
|
||||||
|
async_init_orphan ( async_temp ); \
|
||||||
|
if ( ( rc = START ) == 0 ) \
|
||||||
|
async_wait_progress ( async_temp, &rc );\
|
||||||
|
rc; \
|
||||||
|
} )
|
||||||
|
|
||||||
#endif /* _GPXE_ASYNC_H */
|
#endif /* _GPXE_ASYNC_H */
|
||||||
|
|
Loading…
Reference in New Issue