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