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.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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 process without adding to process list
  115. *
  116. * @v process Process
  117. * @v desc Process descriptor
  118. * @v refcnt Containing object reference count, or NULL
  119. */
  120. static inline __attribute__ (( always_inline )) void
  121. process_init_stopped ( struct process *process,
  122. struct process_descriptor *desc,
  123. struct refcnt *refcnt ) {
  124. INIT_LIST_HEAD ( &process->list );
  125. process->desc = desc;
  126. process->refcnt = refcnt;
  127. }
  128. /**
  129. * Initialise process and add to process list
  130. *
  131. * @v process Process
  132. * @v desc Process descriptor
  133. * @v refcnt Containing object reference count, or NULL
  134. */
  135. static inline __attribute__ (( always_inline )) void
  136. process_init ( struct process *process,
  137. struct process_descriptor *desc,
  138. struct refcnt *refcnt ) {
  139. process_init_stopped ( process, desc, refcnt );
  140. process_add ( process );
  141. }
  142. /**
  143. * Check if process is running
  144. *
  145. * @v process Process
  146. * @ret running Process is running
  147. */
  148. static inline __attribute__ (( always_inline )) int
  149. process_running ( struct process *process ) {
  150. return ( ! list_empty ( &process->list ) );
  151. }
  152. /** Permanent process table */
  153. #define PERMANENT_PROCESSES __table ( struct process, "processes" )
  154. /**
  155. * Declare a permanent process
  156. *
  157. * Permanent processes will be automatically added to the process list
  158. * at initialisation time.
  159. */
  160. #define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
  161. /** Define a permanent process
  162. *
  163. */
  164. #define PERMANENT_PROCESS( name, step ) \
  165. static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \
  166. struct process name __permanent_process = { \
  167. .list = LIST_HEAD_INIT ( name.list ), \
  168. .desc = & name ## _desc, \
  169. .refcnt = NULL, \
  170. };
  171. /**
  172. * Find debugging colourisation for a process
  173. *
  174. * @v process Process
  175. * @ret col Debugging colourisation
  176. *
  177. * Use as the first argument to DBGC() or equivalent macro.
  178. */
  179. #define PROC_COL( process ) process_object ( process )
  180. /** printf() format string for PROC_DBG() */
  181. #define PROC_FMT "%p %s()"
  182. /**
  183. * printf() arguments for representing a process
  184. *
  185. * @v process Process
  186. * @ret args printf() argument list corresponding to PROC_FMT
  187. */
  188. #define PROC_DBG( process ) process_object ( process ), (process)->desc->name
  189. #endif /* _IPXE_PROCESS_H */