Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / process.h
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 );
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         /** Offset of process within containing object */
33         size_t offset;
34         /**
35          * Single-step the process
36          *
37          * This method should execute a single step of the process.
38          * Returning from this method is isomorphic to yielding the
39          * CPU to another process.
40          */
41         void ( * step ) ( void *object );
42         /** Automatically reschedule the process */
43         int reschedule;
44 };
45
46 /**
47  * Define a process step() method
48  *
49  * @v object_type       Implementing method's expected object type
50  * @v step              Implementing method
51  * @ret step            Process step method
52  */
53 #define PROC_STEP( object_type, step )                                        \
54         ( ( ( ( typeof ( step ) * ) NULL ) ==                                 \
55             ( ( void ( * ) ( object_type *object ) ) NULL ) ) ?               \
56           ( void ( * ) ( void *object ) ) step :                              \
57           ( void ( * ) ( void *object ) ) step )
58
59 /**
60  * Calculate offset of process within containing object
61  *
62  * @v object_type       Containing object data type
63  * @v name              Process name (i.e. field within object data type)
64  * @ret offset          Offset of process within containing object
65  */
66 #define process_offset( object_type, name )                                   \
67         ( ( ( ( typeof ( ( ( object_type * ) NULL )->name ) * ) NULL )        \
68             == ( ( struct process * ) NULL ) )                                \
69           ? offsetof ( object_type, name )                                    \
70           : offsetof ( object_type, name ) )
71
72 /**
73  * Define a process descriptor
74  *
75  * @v object_type       Containing object data type
76  * @v process           Process name (i.e. field within object data type)
77  * @v step              Process' step() method
78  * @ret desc            Object interface descriptor
79  */
80 #define PROC_DESC( object_type, process, _step ) {                            \
81                 .offset = process_offset ( object_type, process ),            \
82                 .step = PROC_STEP ( object_type, _step ),                     \
83                 .reschedule = 1,                                              \
84         }
85
86 /**
87  * Define a process descriptor for a process that runs only once
88  *
89  * @v object_type       Containing object data type
90  * @v process           Process name (i.e. field within object data type)
91  * @v step              Process' step() method
92  * @ret desc            Object interface descriptor
93  */
94 #define PROC_DESC_ONCE( object_type, process, _step ) {                       \
95                 .offset = process_offset ( object_type, process ),            \
96                 .step = PROC_STEP ( object_type, _step ),                     \
97                 .reschedule = 0,                                              \
98         }
99
100 /**
101  * Define a process descriptor for a pure process
102  *
103  * A pure process is a process that does not have a containing object.
104  *
105  * @v step              Process' step() method
106  * @ret desc            Object interface descriptor
107  */
108 #define PROC_DESC_PURE( _step ) {                                             \
109                 .offset = 0,                                                  \
110                 .step = PROC_STEP ( struct process, _step ),                  \
111                 .reschedule = 1,                                              \
112         }
113
114 extern void * __attribute__ (( pure ))
115 process_object ( struct process *process );
116 extern void process_add ( struct process *process );
117 extern void process_del ( struct process *process );
118 extern void step ( void );
119
120 /**
121  * Initialise process without adding to process list
122  *
123  * @v process           Process
124  * @v desc              Process descriptor
125  * @v refcnt            Containing object reference count, or NULL
126  */
127 static inline __attribute__ (( always_inline )) void
128 process_init_stopped ( struct process *process,
129                        struct process_descriptor *desc,
130                        struct refcnt *refcnt ) {
131         INIT_LIST_HEAD ( &process->list );
132         process->desc = desc;
133         process->refcnt = refcnt;
134 }
135
136 /**
137  * Initialise process and add to process list
138  *
139  * @v process           Process
140  * @v desc              Process descriptor
141  * @v refcnt            Containing object reference count, or NULL
142  */
143 static inline __attribute__ (( always_inline )) void
144 process_init ( struct process *process,
145                struct process_descriptor *desc,
146                struct refcnt *refcnt ) {
147         process_init_stopped ( process, desc, refcnt );
148         process_add ( process );
149 }
150
151 /**
152  * Check if process is running
153  *
154  * @v process           Process
155  * @ret running         Process is running
156  */
157 static inline __attribute__ (( always_inline )) int
158 process_running ( struct process *process ) {
159         return ( ! list_empty ( &process->list ) );
160 }
161
162 /** Permanent process table */
163 #define PERMANENT_PROCESSES __table ( struct process, "processes" )
164
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
173 /** Define a permanent process
174  *
175  */
176 #define PERMANENT_PROCESS( name, step )                                       \
177 static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step );     \
178 struct process name __permanent_process = {                                   \
179         .list = LIST_HEAD_INIT ( name.list ),                                 \
180         .desc = & name ## _desc,                                              \
181         .refcnt = NULL,                                                       \
182 };
183
184 /**
185  * Find debugging colourisation for a process
186  *
187  * @v process           Process
188  * @ret col             Debugging colourisation
189  *
190  * Use as the first argument to DBGC() or equivalent macro.
191  */
192 #define PROC_COL( process ) process_object ( process )
193
194 /** printf() format string for PROC_DBG() */
195 #define PROC_FMT "%p+%zx"
196
197 /**
198  * printf() arguments for representing a process
199  *
200  * @v process           Process
201  * @ret args            printf() argument list corresponding to PROC_FMT
202  */
203 #define PROC_DBG( process ) process_object ( process ), (process)->desc->offset
204
205 #endif /* _IPXE_PROCESS_H */