source: mainline/uspace/srv/taskman/main.c@ 1be7bee

Last change on this file since 1be7bee was 1be7bee, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

sysman: Move task retval and waiting logic to taskman (partially)

  • two important sessions: NS and taskman
  • depending on boot task vs spawned task those sessions are initiated differently

Conflicts:

uspace/lib/c/generic/async.c
uspace/lib/c/generic/libc.c
uspace/lib/c/generic/task.c
uspace/lib/c/include/ipc/ns.h
uspace/lib/c/include/task.h
uspace/lib/posix/source/sys/wait.c
uspace/srv/loader/main.c
uspace/srv/ns/ns.c

  • Property mode set to 100644
File size: 6.1 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 <adt/prodcons.h>
30#include <assert.h>
31#include <async.h>
32#include <errno.h>
33#include <ipc/services.h>
34#include <ipc/taskman.h>
35#include <loader/loader.h>
36#include <macros.h>
37#include <ns.h>
38#include <stdio.h>
39#include <stdlib.h>
40
41#include "task.h"
42#include "taskman.h"
43
44//TODO move to appropriate header file
45extern async_sess_t *session_primary;
46
47typedef struct {
48 link_t link;
49 async_sess_t *sess;
50} sess_ref_t;
51
52static prodcons_t sess_queue;
53
54
55/*
56 * Static functions
57 */
58static void connect_to_loader(ipc_callid_t iid, ipc_call_t *icall)
59{
60 //TODO explain why we don't explicitly accept connection request
61 /* Spawn a loader. */
62 int rc = loader_spawn("loader");
63
64 if (rc != EOK) {
65 async_answer_0(iid, rc);
66 return;
67 }
68
69 /* Wait until spawned task presents itself to us. */
70 link_t *link = prodcons_consume(&sess_queue);
71 sess_ref_t *sess_ref = list_get_instance(link, sess_ref_t, link);
72
73 /* Forward the connection request (strip interface arg). */
74 async_exch_t *exch = async_exchange_begin(sess_ref->sess);
75 rc = async_forward_fast(iid, exch,
76 IPC_GET_ARG2(*icall),
77 IPC_GET_ARG3(*icall),
78 0, IPC_FF_NONE);
79 async_exchange_end(exch);
80
81 free(sess_ref);
82
83 if (rc != EOK) {
84 async_answer_0(iid, rc);
85 return;
86 }
87
88 /* Everything OK. */
89}
90
91static void loader_to_ns(ipc_callid_t iid, ipc_call_t *icall)
92{
93 /* Do no accept connection request, forward it instead. */
94 async_exch_t *exch = async_exchange_begin(session_primary);
95 int rc = async_forward_fast(iid, exch, 0, 0, 0, IPC_FF_NONE);
96 async_exchange_end(exch);
97
98 if (rc != EOK) {
99 async_answer_0(iid, rc);
100 return;
101 }
102}
103
104static void taskman_ctl_wait(ipc_callid_t iid, ipc_call_t *icall)
105{
106 task_id_t id = (task_id_t)
107 MERGE_LOUP32(IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall));
108 int flags = IPC_GET_ARG3(*icall);
109
110 wait_for_task(id, flags, iid, icall);
111}
112
113static void taskman_ctl_retval(ipc_callid_t iid, ipc_call_t *icall)
114{
115 printf("%s:%i\n", __func__, __LINE__);
116 int rc = task_set_retval(icall);
117 async_answer_0(iid, rc);
118}
119
120static void control_connection_loop(void)
121{
122 while (true) {
123 ipc_call_t call;
124 ipc_callid_t callid = async_get_call(&call);
125
126 if (!IPC_GET_IMETHOD(call)) {
127 /* Client disconnected */
128 break;
129 }
130
131 switch (IPC_GET_IMETHOD(call)) {
132 case TASKMAN_WAIT:
133 taskman_ctl_wait(callid, &call);
134 break;
135 case TASKMAN_RETVAL:
136 taskman_ctl_retval(callid, &call);
137 break;
138 default:
139 async_answer_0(callid, ENOENT);
140 }
141 }
142}
143
144static void control_connection(ipc_callid_t iid, ipc_call_t *icall)
145{
146 /* First, accept connection */
147 async_answer_0(iid, EOK);
148
149 // TODO register task to hash table
150 control_connection_loop();
151}
152
153static void loader_callback(ipc_callid_t iid, ipc_call_t *icall)
154{
155 // TODO check that loader is expected, would probably discard prodcons
156 // scheme
157
158 /* Preallocate session container */
159 sess_ref_t *sess_ref = malloc(sizeof(sess_ref_t));
160 if (sess_ref == NULL) {
161 async_answer_0(iid, ENOMEM);
162 }
163
164
165 /* Create callback connection */
166 sess_ref->sess = async_callback_receive_start(EXCHANGE_ATOMIC, icall);
167 if (sess_ref->sess == NULL) {
168 //TODO different error code?
169 async_answer_0(iid, EINVAL);
170 return;
171 }
172 async_answer_0(iid, EOK);
173
174 link_initialize(&sess_ref->link);
175 prodcons_produce(&sess_queue, &sess_ref->link);
176}
177
178static void taskman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
179{
180 taskman_interface_t iface = IPC_GET_ARG1(*icall);
181 switch (iface) {
182 case TASKMAN_CONNECT_TO_LOADER:
183 connect_to_loader(iid, icall);
184 break;
185 case TASKMAN_LOADER_TO_NS:
186 loader_to_ns(iid, icall);
187 break;
188 case TASKMAN_CONTROL:
189 control_connection(iid, icall);
190 // ---- interrupt here ----
191 // implement control connection body (setup wait)
192 // ------------------------
193 break;
194 default:
195 /* Unknown interface */
196 async_answer_0(iid, ENOENT);
197 }
198}
199
200static void implicit_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
201{
202 taskman_interface_t iface = IPC_GET_ARG1(*icall);
203 switch (iface) {
204 case TASKMAN_LOADER_CALLBACK:
205 loader_callback(iid, icall);
206 // TODO register task to hashtable
207 control_connection_loop();
208 break;
209 default:
210 /* Unknown interface on implicit connection */
211 async_answer_0(iid, EHANGUP);
212 }
213}
214
215/** Build hard coded configuration */
216
217
218int main(int argc, char *argv[])
219{
220 printf(NAME ": HelenOS task manager\n");
221
222 prodcons_initialize(&sess_queue);
223 int rc = task_init();
224 if (rc != EOK) {
225 return rc;
226 }
227
228 /* We're service too */
229 rc = service_register(SERVICE_TASKMAN);
230 if (rc != EOK) {
231 printf("Cannot register at naming service (%i).", rc);
232 return rc;
233 }
234
235 /* Start sysman server */
236 async_set_client_connection(taskman_connection);
237 async_set_implicit_connection(implicit_connection);
238
239 printf(NAME ": Accepting connections\n");
240 //TODO task_retval(EOK);
241 async_manager();
242
243 /* not reached */
244 return 0;
245}
Note: See TracBrowser for help on using the repository browser.