iPXE
process.h
Go to the documentation of this file.
00001 #ifndef _IPXE_PROCESS_H
00002 #define _IPXE_PROCESS_H
00003 
00004 /** @file
00005  *
00006  * Processes
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <ipxe/list.h>
00013 #include <ipxe/refcnt.h>
00014 #include <ipxe/tables.h>
00015 
00016 /** A process */
00017 struct process {
00018         /** List of processes */
00019         struct list_head list;
00020         /** Process descriptor */
00021         struct process_descriptor *desc;
00022         /** Reference counter
00023          *
00024          * If this process is not part of a reference-counted object,
00025          * this field may be NULL.
00026          */
00027         struct refcnt *refcnt;
00028 };
00029 
00030 /** A process descriptor */
00031 struct process_descriptor {
00032         /** Process name */
00033         const char *name;
00034         /** Offset of process within containing object */
00035         size_t offset;
00036         /**
00037          * Single-step the process
00038          *
00039          * This method should execute a single step of the process.
00040          * Returning from this method is isomorphic to yielding the
00041          * CPU to another process.
00042          */
00043         void ( * step ) ( void *object );
00044         /** Automatically reschedule the process */
00045         int reschedule;
00046 };
00047 
00048 /**
00049  * Define a process step() method
00050  *
00051  * @v object_type       Implementing method's expected object type
00052  * @v step              Implementing method
00053  * @ret step            Process step method
00054  */
00055 #define PROC_STEP( object_type, step )                                        \
00056         ( ( ( ( typeof ( step ) * ) NULL ) ==                                 \
00057             ( ( void ( * ) ( object_type *object ) ) NULL ) ) ?               \
00058           ( void ( * ) ( void *object ) ) step :                              \
00059           ( void ( * ) ( void *object ) ) step )
00060 
00061 /**
00062  * Calculate offset of process within containing object
00063  *
00064  * @v object_type       Containing object data type
00065  * @v name              Process name (i.e. field within object data type)
00066  * @ret offset          Offset of process within containing object
00067  */
00068 #define process_offset( object_type, name )                                   \
00069         ( ( ( ( typeof ( ( ( object_type * ) NULL )->name ) * ) NULL )        \
00070             == ( ( struct process * ) NULL ) )                                \
00071           ? offsetof ( object_type, name )                                    \
00072           : offsetof ( object_type, name ) )
00073 
00074 /**
00075  * Define a process descriptor
00076  *
00077  * @v object_type       Containing object data type
00078  * @v process           Process name (i.e. field within object data type)
00079  * @v step              Process' step() method
00080  * @ret desc            Object interface descriptor
00081  */
00082 #define PROC_DESC( object_type, process, _step ) {                            \
00083                 .name = #_step,                                               \
00084                 .offset = process_offset ( object_type, process ),            \
00085                 .step = PROC_STEP ( object_type, _step ),                     \
00086                 .reschedule = 1,                                              \
00087         }
00088 
00089 /**
00090  * Define a process descriptor for a process that runs only once
00091  *
00092  * @v object_type       Containing object data type
00093  * @v process           Process name (i.e. field within object data type)
00094  * @v step              Process' step() method
00095  * @ret desc            Object interface descriptor
00096  */
00097 #define PROC_DESC_ONCE( object_type, process, _step ) {                       \
00098                 .name = #_step,                                               \
00099                 .offset = process_offset ( object_type, process ),            \
00100                 .step = PROC_STEP ( object_type, _step ),                     \
00101                 .reschedule = 0,                                              \
00102         }
00103 
00104 /**
00105  * Define a process descriptor for a pure process
00106  *
00107  * A pure process is a process that does not have a containing object.
00108  *
00109  * @v step              Process' step() method
00110  * @ret desc            Object interface descriptor
00111  */
00112 #define PROC_DESC_PURE( _step ) {                                             \
00113                 .name = #_step,                                               \
00114                 .offset = 0,                                                  \
00115                 .step = PROC_STEP ( struct process, _step ),                  \
00116                 .reschedule = 1,                                              \
00117         }
00118 
00119 extern void * __attribute__ (( pure ))
00120 process_object ( struct process *process );
00121 extern void process_add ( struct process *process );
00122 extern void process_del ( struct process *process );
00123 extern void step ( void );
00124 
00125 /**
00126  * Initialise a static process
00127  *
00128  * @v process           Process
00129  * @v desc              Process descriptor
00130  */
00131 #define PROC_INIT( _process, _desc ) {                                        \
00132                 .list = LIST_HEAD_INIT ( (_process).list ),                   \
00133                 .desc = (_desc),                                              \
00134                 .refcnt = NULL,                                               \
00135         }
00136 
00137 /**
00138  * Initialise process without adding to process list
00139  *
00140  * @v process           Process
00141  * @v desc              Process descriptor
00142  * @v refcnt            Containing object reference count, or NULL
00143  */
00144 static inline __attribute__ (( always_inline )) void
00145 process_init_stopped ( struct process *process,
00146                        struct process_descriptor *desc,
00147                        struct refcnt *refcnt ) {
00148         INIT_LIST_HEAD ( &process->list );
00149         process->desc = desc;
00150         process->refcnt = refcnt;
00151 }
00152 
00153 /**
00154  * Initialise process and add to process list
00155  *
00156  * @v process           Process
00157  * @v desc              Process descriptor
00158  * @v refcnt            Containing object reference count, or NULL
00159  */
00160 static inline __attribute__ (( always_inline )) void
00161 process_init ( struct process *process,
00162                struct process_descriptor *desc,
00163                struct refcnt *refcnt ) {
00164         process_init_stopped ( process, desc, refcnt );
00165         process_add ( process );
00166 }
00167 
00168 /**
00169  * Check if process is running
00170  *
00171  * @v process           Process
00172  * @ret running         Process is running
00173  */
00174 static inline __attribute__ (( always_inline )) int
00175 process_running ( struct process *process ) {
00176         return ( ! list_empty ( &process->list ) );
00177 }
00178 
00179 /** Permanent process table */
00180 #define PERMANENT_PROCESSES __table ( struct process, "processes" )
00181 
00182 /**
00183  * Declare a permanent process
00184  *
00185  * Permanent processes will be automatically added to the process list
00186  * at initialisation time.
00187  */
00188 #define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
00189 
00190 /** Define a permanent process
00191  *
00192  */
00193 #define PERMANENT_PROCESS( name, step )                                       \
00194 static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step );     \
00195 struct process name __permanent_process = PROC_INIT ( name, & name ## _desc );
00196 
00197 /**
00198  * Find debugging colourisation for a process
00199  *
00200  * @v process           Process
00201  * @ret col             Debugging colourisation
00202  *
00203  * Use as the first argument to DBGC() or equivalent macro.
00204  */
00205 #define PROC_COL( process ) process_object ( process )
00206 
00207 /** printf() format string for PROC_DBG() */
00208 #define PROC_FMT "%p %s()"
00209 
00210 /**
00211  * printf() arguments for representing a process
00212  *
00213  * @v process           Process
00214  * @ret args            printf() argument list corresponding to PROC_FMT
00215  */
00216 #define PROC_DBG( process ) process_object ( process ), (process)->desc->name
00217 
00218 #endif /* _IPXE_PROCESS_H */