You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

process.h 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #ifndef _IPXE_PROCESS_H
  2. #define _IPXE_PROCESS_H
  3. /** @file
  4. *
  5. * Processes
  6. *
  7. */
  8. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  9. #include <ipxe/list.h>
  10. #include <ipxe/refcnt.h>
  11. #include <ipxe/tables.h>
  12. /** A process */
  13. struct process {
  14. /** List of processes */
  15. struct list_head list;
  16. /** Process descriptor */
  17. struct process_descriptor *desc;
  18. /** Reference counter
  19. *
  20. * If this process is not part of a reference-counted object,
  21. * this field may be NULL.
  22. */
  23. struct refcnt *refcnt;
  24. };
  25. /** A process descriptor */
  26. struct process_descriptor {
  27. /** Process name */
  28. const char *name;
  29. /** Offset of process within containing object */
  30. size_t offset;
  31. /**
  32. * Single-step the process
  33. *
  34. * This method should execute a single step of the process.
  35. * Returning from this method is isomorphic to yielding the
  36. * CPU to another process.
  37. */
  38. void ( * step ) ( void *object );
  39. /** Automatically reschedule the process */
  40. int reschedule;
  41. };
  42. /**
  43. * Define a process step() method
  44. *
  45. * @v object_type Implementing method's expected object type
  46. * @v step Implementing method
  47. * @ret step Process step method
  48. */
  49. #define PROC_STEP( object_type, step ) \
  50. ( ( ( ( typeof ( step ) * ) NULL ) == \
  51. ( ( void ( * ) ( object_type *object ) ) NULL ) ) ? \
  52. ( void ( * ) ( void *object ) ) step : \
  53. ( void ( * ) ( void *object ) ) step )
  54. /**
  55. * Calculate offset of process within containing object
  56. *
  57. * @v object_type Containing object data type
  58. * @v name Process name (i.e. field within object data type)
  59. * @ret offset Offset of process within containing object
  60. */
  61. #define process_offset( object_type, name ) \
  62. ( ( ( ( typeof ( ( ( object_type * ) NULL )->name ) * ) NULL ) \
  63. == ( ( struct process * ) NULL ) ) \
  64. ? offsetof ( object_type, name ) \
  65. : offsetof ( object_type, name ) )
  66. /**
  67. * Define a process descriptor
  68. *
  69. * @v object_type Containing object data type
  70. * @v process Process name (i.e. field within object data type)
  71. * @v step Process' step() method
  72. * @ret desc Object interface descriptor
  73. */
  74. #define PROC_DESC( object_type, process, _step ) { \
  75. .name = #_step, \
  76. .offset = process_offset ( object_type, process ), \
  77. .step = PROC_STEP ( object_type, _step ), \
  78. .reschedule = 1, \
  79. }
  80. /**
  81. * Define a process descriptor for a process that runs only once
  82. *
  83. * @v object_type Containing object data type
  84. * @v process Process name (i.e. field within object data type)
  85. * @v step Process' step() method
  86. * @ret desc Object interface descriptor
  87. */
  88. #define PROC_DESC_ONCE( object_type, process, _step ) { \
  89. .name = #_step, \
  90. .offset = process_offset ( object_type, process ), \
  91. .step = PROC_STEP ( object_type, _step ), \
  92. .reschedule = 0, \
  93. }
  94. /**
  95. * Define a process descriptor for a pure process
  96. *
  97. * A pure process is a process that does not have a containing object.
  98. *
  99. * @v step Process' step() method
  100. * @ret desc Object interface descriptor
  101. */
  102. #define PROC_DESC_PURE( _step ) { \
  103. .name = #_step, \
  104. .offset = 0, \
  105. .step = PROC_STEP ( struct process, _step ), \
  106. .reschedule = 1, \
  107. }
  108. extern void * __attribute__ (( pure ))
  109. process_object ( struct process *process );
  110. extern void process_add ( struct process *process );
  111. extern void process_del ( struct process *process );
  112. extern void step ( void );
  113. /**
  114. * Initialise a static process
  115. *
  116. * @v process Process
  117. * @v desc Process descriptor
  118. */
  119. #define PROC_INIT( _process, _desc ) { \
  120. .list = LIST_HEAD_INIT ( (_process).list ), \
  121. .desc = (_desc), \
  122. .refcnt = NULL, \
  123. }
  124. /**
  125. * Initialise process without adding to process list
  126. *
  127. * @v process Process
  128. * @v desc Process descriptor
  129. * @v refcnt Containing object reference count, or NULL
  130. */
  131. static inline __attribute__ (( always_inline )) void
  132. process_init_stopped ( struct process *process,
  133. struct process_descriptor *desc,
  134. struct refcnt *refcnt ) {
  135. INIT_LIST_HEAD ( &process->list );
  136. process->desc = desc;
  137. process->refcnt = refcnt;
  138. }
  139. /**
  140. * Initialise process and add to process list
  141. *
  142. * @v process Process
  143. * @v desc Process descriptor
  144. * @v refcnt Containing object reference count, or NULL
  145. */
  146. static inline __attribute__ (( always_inline )) void
  147. process_init ( struct process *process,
  148. struct process_descriptor *desc,
  149. struct refcnt *refcnt ) {
  150. process_init_stopped ( process, desc, refcnt );
  151. process_add ( process );
  152. }
  153. /**
  154. * Check if process is running
  155. *
  156. * @v process Process
  157. * @ret running Process is running
  158. */
  159. static inline __attribute__ (( always_inline )) int
  160. process_running ( struct process *process ) {
  161. return ( ! list_empty ( &process->list ) );
  162. }
  163. /** Permanent process table */
  164. #define PERMANENT_PROCESSES __table ( struct process, "processes" )
  165. /**
  166. * Declare a permanent process
  167. *
  168. * Permanent processes will be automatically added to the process list
  169. * at initialisation time.
  170. */
  171. #define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
  172. /** Define a permanent process
  173. *
  174. */
  175. #define PERMANENT_PROCESS( name, step ) \
  176. static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \
  177. struct process name __permanent_process = PROC_INIT ( name, & name ## _desc );
  178. /**
  179. * Find debugging colourisation for a process
  180. *
  181. * @v process Process
  182. * @ret col Debugging colourisation
  183. *
  184. * Use as the first argument to DBGC() or equivalent macro.
  185. */
  186. #define PROC_COL( process ) process_object ( process )
  187. /** printf() format string for PROC_DBG() */
  188. #define PROC_FMT "%p %s()"
  189. /**
  190. * printf() arguments for representing a process
  191. *
  192. * @v process Process
  193. * @ret args printf() argument list corresponding to PROC_FMT
  194. */
  195. #define PROC_DBG( process ) process_object ( process ), (process)->desc->name
  196. #endif /* _IPXE_PROCESS_H */