source: mainline/uspace/srv/sysman/main.c@ 5a88d87

Last change on this file since 5a88d87 was 4ff66ae, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

taskman: Bind events dump to register handler

  • So that no events are processed twice or omitted.
  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 * Copyright (c) 2015 Michal Koutny
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <async.h>
30#include <errno.h>
31#include <fibril.h>
32#include <ipc/sysman.h>
33#include <macros.h>
34#include <ns.h>
35#include <stddef.h>
36#include <stdio.h>
37#include <str.h>
38#include <taskman.h>
39
40#include "repo.h"
41#include "connection_broker.h"
42#include "connection_ctl.h"
43#include "edge.h"
44#include "job_queue.h"
45#include "log.h"
46#include "sysman.h"
47#include "sm_task.h"
48#include "unit.h"
49
50#define NAME "sysman"
51
52#define INITRD_DEVICE "bd/initrd"
53#define INITRD_MOUNT_POINT "/"
54#define INITRD_CFG_PATH "/cfg/sysman"
55
56#define TARGET_INIT "initrd.tgt"
57#define TARGET_ROOTFS "rootfs.tgt"
58#define TARGET_DEFAULT "default.tgt"
59
60#define UNIT_MNT_INITRD "initrd.mnt"
61#define UNIT_CFG_INITRD "init.cfg"
62
63
64static const char *target_sequence[] = {
65 TARGET_INIT,
66 TARGET_ROOTFS,
67 TARGET_DEFAULT,
68 NULL
69};
70
71/*
72 * Forward declarations
73 */
74static void prepare_and_run_job(const char **target_name_ptr);
75
76/*
77 * Static functions
78 */
79
80static void sysman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
81{
82 sysman_interface_t iface = IPC_GET_ARG1(*icall);
83 switch (iface) {
84 case SYSMAN_PORT_BROKER:
85 sysman_connection_broker(iid, icall);
86 break;
87 case SYSMAN_PORT_CTL:
88 sysman_connection_ctl(iid, icall);
89 break;
90 default:
91 /* Unknown interface */
92 async_answer_0(iid, ENOENT);
93 }
94}
95
96/** Build hard coded configuration */
97static int create_entry_configuration(void) {
98 int rc;
99 unit_t *mnt_initrd = NULL;
100 unit_t *cfg_init = NULL;
101 unit_t *tgt_init = NULL;
102
103 mnt_initrd = unit_create(UNIT_MOUNT);
104 if (mnt_initrd == NULL) {
105 rc = ENOMEM;
106 goto fail;
107 }
108 mnt_initrd->name = str_dup(UNIT_MNT_INITRD);
109 CAST_MNT(mnt_initrd)->type = str_dup(STRING(RDFMT));
110 CAST_MNT(mnt_initrd)->mountpoint = str_dup(INITRD_MOUNT_POINT);
111 CAST_MNT(mnt_initrd)->device = str_dup(INITRD_DEVICE);
112 CAST_MNT(mnt_initrd)->autostart = false;
113 CAST_MNT(mnt_initrd)->blocking = true;
114
115 cfg_init = unit_create(UNIT_CONFIGURATION);
116 if (cfg_init == NULL) {
117 rc = ENOMEM;
118 goto fail;
119 }
120 cfg_init->name = str_dup(UNIT_CFG_INITRD);
121 CAST_CFG(cfg_init)->path = str_dup(INITRD_CFG_PATH);
122
123 tgt_init = unit_create(UNIT_TARGET);
124 if (tgt_init == NULL) {
125 rc = ENOMEM;
126 goto fail;
127 }
128 tgt_init->name = str_dup(TARGET_INIT);
129
130
131 /*
132 * Add units to configuration and start the default target.
133 */
134 repo_begin_update();
135
136 repo_add_unit(mnt_initrd);
137 repo_add_unit(cfg_init);
138 repo_add_unit(tgt_init);
139
140 rc = edge_connect(tgt_init, cfg_init);
141 if (rc != EOK) {
142 goto rollback;
143 }
144
145 rc = edge_connect(cfg_init, mnt_initrd);
146 if (rc != EOK) {
147 goto rollback;
148 }
149
150 repo_commit();
151
152 return EOK;
153
154fail:
155 unit_destroy(&tgt_init);
156 unit_destroy(&cfg_init);
157 unit_destroy(&mnt_initrd);
158 return rc;
159
160rollback:
161 repo_rollback();
162 return rc;
163}
164
165static void sequence_job_handler(void *object, void *arg)
166{
167 job_t *job = object;
168 if (job->retval == JOB_FAILED) {
169 sysman_log(LVL_ERROR, "Failed to start '%s'.", unit_name(job->unit));
170 job_del_ref(&job);
171 return;
172 }
173 job_del_ref(&job);
174
175 const char **target_name_ptr = arg;
176 prepare_and_run_job(target_name_ptr + 1);
177}
178
179static void prepare_and_run_job(const char **target_name_ptr)
180{
181 const char *target_name = *target_name_ptr;
182
183 if (target_name == NULL) {
184 sysman_log(LVL_NOTE, "All initial units started.");
185 return;
186 }
187
188 /* Previous targets should have loaded new units */
189 unit_t *tgt = repo_find_unit_by_name(target_name);
190 if (tgt == NULL) {
191 sysman_log(LVL_ERROR,
192 "Expected unit '%s' not found in configuration.",
193 target_name);
194 return;
195 }
196
197 int rc = sysman_run_job(tgt, STATE_STARTED, &sequence_job_handler,
198 target_name_ptr);
199
200 if (rc != EOK) {
201 sysman_log(LVL_FATAL, "Cannot create job for '%s'.", target_name);
202 }
203}
204
205int main(int argc, char *argv[])
206{
207 async_set_client_connection(sysman_connection);
208 printf(NAME ": HelenOS system daemon\n");
209
210 /*
211 * Initialize global structures
212 */
213 // TODO check return values and abort start
214 repo_init();
215 sysman_events_init();
216 job_queue_init();
217
218 /*
219 * Create initial configuration while we are in a single fibril
220 */
221 int rc = create_entry_configuration();
222 if (rc != EOK) {
223 sysman_log(LVL_FATAL,
224 "Could not create initial configuration (%i).", rc);
225 return rc;
226 }
227
228 /*
229 * Event loop runs in separate fibril, all consequent access to global
230 * structure is made from this fibril only.
231 */
232 fid_t event_loop_fibril = fibril_create(sysman_events_loop, NULL);
233 fibril_add_ready(event_loop_fibril);
234
235 sysman_log(LVL_DEBUG, "Debugging pause...\n");
236 async_usleep(1 * 1000000);
237 sysman_log(LVL_DEBUG, "Debugging pause ended.\n");
238
239 /* We're service too */
240 rc = service_register(SERVICE_SYSMAN);
241 if (rc != EOK) {
242 sysman_log(LVL_FATAL,
243 "Cannot register at naming service (%i).", rc);
244 return rc;
245 }
246
247 /* Start listening task events and scan boot time tasks */
248 rc = sm_task_start();
249 if (rc != EOK) {
250 sysman_log(LVL_FATAL,
251 "Cannot scan boot time tasks (%i).", rc);
252 return rc;
253 }
254
255 /* Queue first job from sequence */
256 prepare_and_run_job(&target_sequence[0]);
257
258 /* Start sysman server */
259
260 printf(NAME ": Accepting connections\n");
261 task_retval(0);
262 async_manager();
263
264 /* not reached */
265 return 0;
266}
Note: See TracBrowser for help on using the repository browser.