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 process without adding to process list
00127  *
00128  * @v process           Process
00129  * @v desc              Process descriptor
00130  * @v refcnt            Containing object reference count, or NULL
00131  */
00132 static inline __attribute__ (( always_inline )) void
00133 process_init_stopped ( struct process *process,
00134                        struct process_descriptor *desc,
00135                        struct refcnt *refcnt ) {
00136         INIT_LIST_HEAD ( &process->list );
00137         process->desc = desc;
00138         process->refcnt = refcnt;
00139 }
00140 
00141 /**
00142  * Initialise process and add to process list
00143  *
00144  * @v process           Process
00145  * @v desc              Process descriptor
00146  * @v refcnt            Containing object reference count, or NULL
00147  */
00148 static inline __attribute__ (( always_inline )) void
00149 process_init ( struct process *process,
00150                struct process_descriptor *desc,
00151                struct refcnt *refcnt ) {
00152         process_init_stopped ( process, desc, refcnt );
00153         process_add ( process );
00154 }
00155 
00156 /**
00157  * Check if process is running
00158  *
00159  * @v process           Process
00160  * @ret running         Process is running
00161  */
00162 static inline __attribute__ (( always_inline )) int
00163 process_running ( struct process *process ) {
00164         return ( ! list_empty ( &process->list ) );
00165 }
00166 
00167 /** Permanent process table */
00168 #define PERMANENT_PROCESSES __table ( struct process, "processes" )
00169 
00170 /**
00171  * Declare a permanent process
00172  *
00173  * Permanent processes will be automatically added to the process list
00174  * at initialisation time.
00175  */
00176 #define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
00177 
00178 /** Define a permanent process
00179  *
00180  */
00181 #define PERMANENT_PROCESS( name, step )                                       \
00182 static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step );     \
00183 struct process name __permanent_process = {                                   \
00184         .list = LIST_HEAD_INIT ( name.list ),                                 \
00185         .desc = & name ## _desc,                                              \
00186         .refcnt = NULL,                                                       \
00187 };
00188 
00189 /**
00190  * Find debugging colourisation for a process
00191  *
00192  * @v process           Process
00193  * @ret col             Debugging colourisation
00194  *
00195  * Use as the first argument to DBGC() or equivalent macro.
00196  */
00197 #define PROC_COL( process ) process_object ( process )
00198 
00199 /** printf() format string for PROC_DBG() */
00200 #define PROC_FMT "%p %s()"
00201 
00202 /**
00203  * printf() arguments for representing a process
00204  *
00205  * @v process           Process
00206  * @ret args            printf() argument list corresponding to PROC_FMT
00207  */
00208 #define PROC_DBG( process ) process_object ( process ), (process)->desc->name
00209 
00210 #endif /* _IPXE_PROCESS_H */