VM: full munmap
[minix.git] / lib / libsys / sef_liveupdate.c
blob4219eeb70253d42d71cb0351b67688b15f0e2999
1 #include "syslib.h"
2 #include <assert.h>
3 #include <minix/sysutil.h>
5 /* SEF Live update variables. */
6 static int sef_lu_state;
8 /* SEF Live update callbacks. */
9 static struct sef_cbs {
10 sef_cb_lu_prepare_t sef_cb_lu_prepare;
11 sef_cb_lu_state_isvalid_t sef_cb_lu_state_isvalid;
12 sef_cb_lu_state_changed_t sef_cb_lu_state_changed;
13 sef_cb_lu_state_dump_t sef_cb_lu_state_dump;
14 sef_cb_lu_state_save_t sef_cb_lu_state_save;
15 sef_cb_lu_response_t sef_cb_lu_response;
16 } sef_cbs = {
17 SEF_CB_LU_PREPARE_DEFAULT,
18 SEF_CB_LU_STATE_ISVALID_DEFAULT,
19 SEF_CB_LU_STATE_CHANGED_DEFAULT,
20 SEF_CB_LU_STATE_DUMP_DEFAULT,
21 SEF_CB_LU_STATE_SAVE_DEFAULT,
22 SEF_CB_LU_RESPONSE_DEFAULT
25 /* SEF Live update prototypes for sef_receive(). */
26 void do_sef_lu_before_receive(void);
27 int do_sef_lu_request(message *m_ptr);
29 /* SEF Live update helpers. */
30 static void sef_lu_ready(int result);
32 /* Debug. */
33 EXTERN char* sef_debug_header(void);
34 static int sef_lu_debug_cycle = 0;
36 /* Information about SELF. */
37 EXTERN endpoint_t sef_self_endpoint;
38 EXTERN int sef_self_first_receive_done;
40 /*===========================================================================*
41 * do_sef_lu_before_receive *
42 *===========================================================================*/
43 void do_sef_lu_before_receive()
45 /* Handle SEF Live update before receive events. */
46 int r;
48 /* Initialize on first receive. */
49 if(!sef_self_first_receive_done) {
50 sef_lu_state = SEF_LU_STATE_NULL;
53 /* Nothing to do if we are not preparing for a live update. */
54 if(sef_lu_state == SEF_LU_STATE_NULL) {
55 return;
58 /* Debug. */
59 #if SEF_LU_DEBUG
60 sef_lu_debug_cycle++;
61 sef_lu_debug_begin();
62 sef_lu_dprint("%s, cycle=%d. Dumping state variables:\n",
63 sef_debug_header(), sef_lu_debug_cycle);
64 sef_cbs.sef_cb_lu_state_dump(sef_lu_state);
65 sef_lu_debug_end();
66 #endif
68 /* Let the callback code handle the event.
69 * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately.
71 r = OK;
72 if(sef_lu_state != SEF_LU_STATE_WORK_FREE) {
73 r = sef_cbs.sef_cb_lu_prepare(sef_lu_state);
75 if(r == OK) {
76 sef_lu_ready(OK);
80 /*===========================================================================*
81 * do_sef_lu_request *
82 *===========================================================================*/
83 int do_sef_lu_request(message *m_ptr)
85 /* Handle a SEF Live update request. */
86 int state, old_state, is_valid_state;
88 sef_lu_debug_cycle = 0;
89 old_state = sef_lu_state;
90 state = m_ptr->RS_LU_STATE;
92 /* Deal with prepare cancel requests first. */
93 is_valid_state = (state == SEF_LU_STATE_NULL);
95 /* Otherwise only accept live update requests with a valid state. */
96 is_valid_state = is_valid_state || sef_cbs.sef_cb_lu_state_isvalid(state);
97 if(!is_valid_state) {
98 if(sef_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_NULL) {
99 sef_lu_ready(ENOSYS);
101 else {
102 sef_lu_ready(EINVAL);
105 else {
106 /* Set the new live update state. */
107 sef_lu_state = state;
109 /* If the live update state changed, let the callback code
110 * handle the rest.
112 if(old_state != sef_lu_state) {
113 sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
117 /* Return OK not to let anybody else intercept the request. */
118 return(OK);
121 /*===========================================================================*
122 * sef_lu_ready *
123 *===========================================================================*/
124 static void sef_lu_ready(int result)
126 message m;
127 int old_state, r;
129 #if SEF_LU_DEBUG
130 sef_lu_debug_begin();
131 sef_lu_dprint("%s, cycle=%d. Ready to update with result: %d%s\n",
132 sef_debug_header(), sef_lu_debug_cycle,
133 result, (result == OK ? "(OK)" : ""));
134 sef_lu_debug_end();
135 #endif
137 /* If result is OK, let the callback code save
138 * any state that must be carried over to the new version.
140 if(result == OK) {
141 r = sef_cbs.sef_cb_lu_state_save(sef_lu_state);
142 if(r != OK) {
143 /* Abort update if callback returned error. */
144 result = r;
148 /* Let the callback code produce a live update response and block.
149 * We should get beyond this point only if either result is an error or
150 * something else goes wrong in the callback code.
152 m.m_source = sef_self_endpoint;
153 m.m_type = RS_LU_PREPARE;
154 m.RS_LU_STATE = sef_lu_state;
155 m.RS_LU_RESULT = result;
156 r = sef_cbs.sef_cb_lu_response(&m);
158 #if SEF_LU_DEBUG
159 sef_lu_debug_begin();
160 sef_lu_dprint("%s, cycle=%d. The %s aborted the update with result %d!\n",
161 sef_debug_header(), sef_lu_debug_cycle,
162 (result == OK ? "server" : "client"),
163 (result == OK ? r : result)); /* EINTR if update was canceled. */
164 sef_lu_debug_end();
165 #endif
167 /* Something went wrong. Update was aborted and we didn't get updated.
168 * Restore things back to normal and continue executing.
170 old_state = sef_lu_state;
171 sef_lu_state = SEF_LU_STATE_NULL;
172 if(old_state != sef_lu_state) {
173 sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
177 /*===========================================================================*
178 * sef_setcb_lu_prepare *
179 *===========================================================================*/
180 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb)
182 assert(cb != NULL);
183 sef_cbs.sef_cb_lu_prepare = cb;
186 /*===========================================================================*
187 * sef_setcb_lu_state_isvalid *
188 *===========================================================================*/
189 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb)
191 assert(cb != NULL);
192 sef_cbs.sef_cb_lu_state_isvalid = cb;
195 /*===========================================================================*
196 * sef_setcb_lu_state_changed *
197 *===========================================================================*/
198 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb)
200 assert(cb != NULL);
201 sef_cbs.sef_cb_lu_state_changed = cb;
204 /*===========================================================================*
205 * sef_setcb_lu_state_dump *
206 *===========================================================================*/
207 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb)
209 assert(cb != NULL);
210 sef_cbs.sef_cb_lu_state_dump = cb;
213 /*===========================================================================*
214 * sef_setcb_lu_state_save *
215 *===========================================================================*/
216 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb)
218 assert(cb != NULL);
219 sef_cbs.sef_cb_lu_state_save = cb;
222 /*===========================================================================*
223 * sef_setcb_lu_response *
224 *===========================================================================*/
225 void sef_setcb_lu_response(sef_cb_lu_response_t cb)
227 assert(cb != NULL);
228 sef_cbs.sef_cb_lu_response = cb;
231 /*===========================================================================*
232 * sef_cb_lu_prepare_null *
233 *===========================================================================*/
234 int sef_cb_lu_prepare_null(int UNUSED(state))
236 return ENOTREADY;
239 /*===========================================================================*
240 * sef_cb_lu_state_isvalid_null *
241 *===========================================================================*/
242 int sef_cb_lu_state_isvalid_null(int UNUSED(state))
244 return FALSE;
247 /*===========================================================================*
248 * sef_cb_lu_state_changed_null *
249 *===========================================================================*/
250 void sef_cb_lu_state_changed_null(int UNUSED(old_state),
251 int UNUSED(state))
255 /*===========================================================================*
256 * sef_cb_lu_state_dump_null *
257 *===========================================================================*/
258 void sef_cb_lu_state_dump_null(int UNUSED(state))
260 sef_lu_dprint("NULL\n");
263 /*===========================================================================*
264 * sef_cb_lu_state_save_null *
265 *===========================================================================*/
266 int sef_cb_lu_state_save_null(int UNUSED(result))
268 return OK;
271 /*===========================================================================*
272 * sef_cb_lu_response_null *
273 *===========================================================================*/
274 int sef_cb_lu_response_null(message * UNUSED(m_ptr))
276 return ENOSYS;
279 /*===========================================================================*
280 * sef_cb_lu_prepare_always_ready *
281 *===========================================================================*/
282 int sef_cb_lu_prepare_always_ready(int UNUSED(state))
284 return OK;
287 /*===========================================================================*
288 * sef_cb_lu_prepare_never_ready *
289 *===========================================================================*/
290 int sef_cb_lu_prepare_never_ready(int UNUSED(state))
292 #if SEF_LU_DEBUG
293 sef_lu_debug_begin();
294 sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n",
295 sef_debug_header(), sef_lu_debug_cycle);
296 sef_lu_debug_end();
297 #endif
299 return ENOTREADY;
302 /*===========================================================================*
303 * sef_cb_lu_prepare_crash *
304 *===========================================================================*/
305 int sef_cb_lu_prepare_crash(int UNUSED(state))
307 panic("Simulating a crash at update prepare time...");
309 return OK;
312 /*===========================================================================*
313 * sef_cb_lu_state_isvalid_standard *
314 *===========================================================================*/
315 int sef_cb_lu_state_isvalid_standard(int state)
317 return SEF_LU_STATE_IS_STANDARD(state);
320 /*===========================================================================*
321 * sef_cb_lu_state_isvalid_workfree *
322 *===========================================================================*/
323 int sef_cb_lu_state_isvalid_workfree(int state)
325 return (state == SEF_LU_STATE_WORK_FREE);
328 /*===========================================================================*
329 * sef_cb_lu_response_rs_reply *
330 *===========================================================================*/
331 int sef_cb_lu_response_rs_reply(message *m_ptr)
333 int r;
335 /* Inform RS that we're ready with the given result. */
336 r = sendrec(RS_PROC_NR, m_ptr);
337 if ( r != OK) {
338 return r;
341 return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type;