Skip to content

Commit

Permalink
[interface] Provide the ability to shut down multiple interfaces
Browse files Browse the repository at this point in the history
Shutting down (and optionally restarting) multiple interfaces is
fraught with problems if there are loops in the interface connectivity
(e.g. the HTTP content-decoded and transfer-decoded interfaces, which
will generally loop back to each other).  Various workarounds
currently exist across the codebase, generally involving preceding
calls to intf_nullify() to avoid problems due to known loops.

Provide intfs_shutdown() and intfs_restart() to allow all of an
object's interfaces to be shut down (or restarted) in a single call,
without having to worry about potential external loops.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Feb 2, 2017
1 parent a8f80a7 commit 23b788e
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
69 changes: 69 additions & 0 deletions src/core/interface.c
Expand Up @@ -290,6 +290,41 @@ void intf_shutdown ( struct interface *intf, int rc ) {
intf_unplug ( &tmp );
}

/**
* Shut down multiple object interfaces
*
* @v intfs Object interfaces
* @v rc Reason for close
*/
void intfs_vshutdown ( va_list intfs, int rc ) {
struct interface *intf;
va_list tmp;

/* Nullify all interfaces to avoid potential loops */
va_copy ( tmp, intfs );
while ( ( intf = va_arg ( tmp, struct interface * ) ) )
intf_nullify ( intf );
va_end ( tmp );

/* Shut down all interfaces */
while ( ( intf = va_arg ( intfs, struct interface * ) ) )
intf_shutdown ( intf, rc );
}

/**
* Shut down multiple object interfaces
*
* @v rc Reason for close
* @v ... Object interfaces
*/
void intfs_shutdown ( int rc, ... ) {
va_list intfs;

va_start ( intfs, rc );
intfs_vshutdown ( intfs, rc );
va_end ( intfs );
}

/**
* Shut down and restart an object interface
*
Expand All @@ -316,6 +351,40 @@ void intf_restart ( struct interface *intf, int rc ) {
intf_reinit ( intf );
}

/**
* Shut down and restart multiple object interfaces
*
* @v intfs Object interfaces
* @v rc Reason for close
*/
void intfs_vrestart ( va_list intfs, int rc ) {
struct interface *intf;
va_list tmp;

/* Shut down all interfaces */
va_copy ( tmp, intfs );
intfs_vshutdown ( tmp, rc );
va_end ( tmp );

/* Reinitialise all interfaces */
while ( ( intf = va_arg ( intfs, struct interface * ) ) )
intf_reinit ( intf );
}

/**
* Shut down and restart multiple object interfaces
*
* @v rc Reason for close
* @v ... Object interfaces
*/
void intfs_restart ( int rc, ... ) {
va_list intfs;

va_start ( intfs, rc );
intfs_vrestart ( intfs, rc );
va_end ( intfs );
}

/**
* Poke an object interface
*
Expand Down
5 changes: 5 additions & 0 deletions src/include/ipxe/interface.h
Expand Up @@ -10,6 +10,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <stddef.h>
#include <stdarg.h>
#include <ipxe/refcnt.h>

/** An object interface operation */
Expand Down Expand Up @@ -148,7 +149,11 @@ extern void intf_close ( struct interface *intf, int rc );
typeof ( void ( object_type, int rc ) )

extern void intf_shutdown ( struct interface *intf, int rc );
extern void intfs_vshutdown ( va_list intfs, int rc );
extern void intfs_shutdown ( int rc, ... ) __attribute__ (( sentinel ));
extern void intf_restart ( struct interface *intf, int rc );
extern void intfs_vrestart ( va_list intfs, int rc );
extern void intfs_restart ( int rc, ... ) __attribute__ (( sentinel ));

extern void intf_poke ( struct interface *intf,
void ( type ) ( struct interface *intf ) );
Expand Down

0 comments on commit 23b788e

Please sign in to comment.