diff --git a/src/core/process.c b/src/core/process.c index c087f16d..0583a398 100644 --- a/src/core/process.c +++ b/src/core/process.c @@ -31,25 +31,43 @@ static LIST_HEAD ( run_queue ); /** - * Add process to run queue + * Add process to process list * * @v process Process */ -void schedule ( struct process *process ) { +void process_add ( struct process *process ) { + ref_get ( process->refcnt ); list_add_tail ( &process->list, &run_queue ); } +/** + * Remove process from process list + * + * @v process Process + * + * It is safe to call process_del() multiple times; further calls will + * have no effect. + */ +void process_del ( struct process *process ) { + if ( ! list_empty ( &process->list ) ) { + list_del ( &process->list ); + INIT_LIST_HEAD ( &process->list ); + ref_put ( process->refcnt ); + } +} + /** * Single-step a single process * - * This removes the first process from the run queue and executes a - * single step of that process. + * This executes a single step of the first process in the run queue, + * and moves the process to the end of the run queue. */ void step ( void ) { struct process *process; list_for_each_entry ( process, &run_queue, list ) { list_del ( &process->list ); + list_add_tail ( &process->list, &run_queue ); process->step ( process ); break; } diff --git a/src/include/gpxe/process.h b/src/include/gpxe/process.h index 83ff8393..c0837fa4 100644 --- a/src/include/gpxe/process.h +++ b/src/include/gpxe/process.h @@ -8,6 +8,7 @@ */ #include +#include /** A process */ struct process { @@ -19,14 +20,46 @@ struct process { * This method should execute a single step of the process. * Returning from this method is isomorphic to yielding the * CPU to another process. - * - * If the process wishes to be executed again, it must re-add - * itself to the run queue using schedule(). */ void ( * step ) ( struct process *process ); + /** Reference counter + * + * If this interface is not part of a reference-counted + * object, this field may be NULL. + */ + struct refcnt *refcnt; }; -extern void schedule ( struct process *process ); +extern void process_add ( struct process *process ); +extern void process_del ( struct process *process ); extern void step ( void ); +/** + * Initialise process without adding to process list + * + * @v process Process + * @v step Process' step() method + */ +static inline __attribute__ (( always_inline )) void +process_init_stopped ( struct process *process, + void ( * step ) ( struct process *process ), + struct refcnt *refcnt ) { + process->step = step; + process->refcnt = refcnt; +} + +/** + * Initialise process and add to process list + * + * @v process Process + * @v step Process' step() method + */ +static inline __attribute__ (( always_inline )) void +process_init ( struct process *process, + void ( * step ) ( struct process *process ), + struct refcnt *refcnt ) { + process_init_stopped ( process, step, refcnt ); + process_add ( process ); +} + #endif /* _GPXE_PROCESS_H */ diff --git a/src/include/gpxe/retry.h b/src/include/gpxe/retry.h index 57be432e..e0c0248b 100644 --- a/src/include/gpxe/retry.h +++ b/src/include/gpxe/retry.h @@ -37,4 +37,15 @@ struct retry_timer { extern void start_timer ( struct retry_timer *timer ); extern void stop_timer ( struct retry_timer *timer ); +/** + * Test to see if timer is currently running + * + * @v timer Retry timer + * @ret running Non-zero if timer is running + */ +static inline __attribute__ (( always_inline )) unsigned long +timer_running ( struct retry_timer *timer ) { + return ( timer->start ); +} + #endif /* _GPXE_RETRY_H */ diff --git a/src/net/netdevice.c b/src/net/netdevice.c index c1ad5f68..ddcb296f 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -388,7 +388,7 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, * This polls all interfaces for received packets, and processes * packets from the RX queue. */ -static void net_step ( struct process *process ) { +static void net_step ( struct process *process __unused ) { struct net_device *netdev; struct io_buffer *iobuf; @@ -410,9 +410,6 @@ static void net_step ( struct process *process ) { netdev->ll_protocol->rx ( iobuf, netdev ); } } - - /* Re-schedule ourself */ - schedule ( process ); } /** Networking stack process */ @@ -422,7 +419,7 @@ static struct process net_process = { /** Initialise the networking stack process */ static void init_net ( void ) { - schedule ( &net_process ); + process_add ( &net_process ); } INIT_FN ( INIT_PROCESS, init_net, NULL, NULL ); diff --git a/src/net/retry.c b/src/net/retry.c index cd683f5b..f8c34b81 100644 --- a/src/net/retry.c +++ b/src/net/retry.c @@ -64,7 +64,7 @@ static LIST_HEAD ( timers ); * be stopped and the timer's callback function will be called. */ void start_timer ( struct retry_timer *timer ) { - if ( ! timer->start ) + if ( ! timer_running ( timer ) ) list_add ( &timer->list, &timers ); timer->start = currticks(); if ( timer->timeout < MIN_TIMEOUT ) @@ -86,7 +86,7 @@ void stop_timer ( struct retry_timer *timer ) { unsigned long runtime; /* If timer was already stopped, do nothing */ - if ( ! timer->start ) + if ( ! timer_running ( timer ) ) return; list_del ( &timer->list ); @@ -153,7 +153,7 @@ static void timer_expired ( struct retry_timer *timer ) { * * @v process Retry timer process */ -static void retry_step ( struct process *process ) { +static void retry_step ( struct process *process __unused ) { struct retry_timer *timer; struct retry_timer *tmp; unsigned long now = currticks(); @@ -164,8 +164,6 @@ static void retry_step ( struct process *process ) { if ( used >= timer->timeout ) timer_expired ( timer ); } - - schedule ( process ); } /** Retry timer process */ @@ -175,7 +173,7 @@ static struct process retry_process = { /** Initialise the retry timer module */ static void init_retry ( void ) { - schedule ( &retry_process ); + process_add ( &retry_process ); } INIT_FN ( INIT_PROCESS, init_retry, NULL, NULL );