mirror of
https://github.com/xcat2/xNBA.git
synced 2025-01-11 10:17:49 +00:00
Modify process semantics; rescheduling is now automatic.
Add reference-counting to processes. Add timer_running() test.
This commit is contained in:
parent
6006bed530
commit
3601103381
@ -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;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <gpxe/list.h>
|
||||
#include <gpxe/refcnt.h>
|
||||
|
||||
/** 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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user