Changeset 012dd8e in mainline for uspace/srv
- Timestamp:
- 2019-08-07T09:15:30Z (7 years ago)
- Children:
- e8747bd8
- Parents:
- 780c8ce
- git-author:
- Michal Koutný <xm.koutny+hos@…> (2015-11-01 00:08:04)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-07 09:15:30)
- Location:
- uspace/srv
- Files:
-
- 7 edited
-
loader/main.c (modified) (9 diffs)
-
ns/ns.c (modified) (3 diffs)
-
sysman/main.c (modified) (1 diff)
-
taskman/event.c (modified) (3 diffs)
-
taskman/main.c (modified) (16 diffs)
-
taskman/task.c (modified) (3 diffs)
-
taskman/task.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/loader/main.c
r780c8ce r012dd8e 35 35 * The program loader is a special init binary. Its image is used 36 36 * to create a new task upon a @c task_spawn syscall. It has a phone connected 37 * to the caller of t e syscall. The formal caller (taskman) performs a37 * to the caller of the syscall. The formal caller (taskman) performs a 38 38 * handshake with loader so that apparent caller can communicate with the 39 39 * loader. … … 60 60 #include <ipc/loader.h> 61 61 #include <loader/pcb.h> 62 #include <ns.h> 62 63 #include <str.h> 63 64 #include <sys/types.h> 65 #include <task.h> 64 66 #include <taskman.h> 65 67 #include <unistd.h> … … 72 74 #endif 73 75 76 #define NAME "loader" 74 77 #define DPRINTF(...) ((void) 0) 75 78 … … 80 83 /** The Program control block */ 81 84 static pcb_t pcb; 82 83 /** Primary IPC session */84 static async_sess_t *session_primary = NULL;85 86 /** Session to taskman (typically our spawner) */87 static async_sess_t *session_taskman = NULL;88 85 89 86 /** Current working directory */ … … 105 102 /** Used to limit number of connections to one. */ 106 103 static bool connected = false; 107 108 /** Ensure synchronization of handshake and connection fibrils. */109 static bool handshake_complete = false;110 FIBRIL_MUTEX_INITIALIZE(handshake_mtx);111 FIBRIL_CONDVAR_INITIALIZE(handshake_cv);112 104 113 105 static void ldr_get_taskid(ipc_call_t *req) … … 337 329 DPRINTF("PCB set.\n"); 338 330 339 pcb.session_primary = session_primary; 340 pcb.session_taskman = session_taskman; 331 pcb.session_taskman = taskman_get_session(); 341 332 342 333 pcb.cwd = cwd; … … 394 385 static void ldr_connection(ipc_call_t *icall, void *arg) 395 386 { 396 /* Wait for handshake */397 fibril_mutex_lock(&handshake_mtx);398 while (!handshake_complete) {399 fibril_condvar_wait(&handshake_cv, &handshake_mtx);400 }401 fibril_mutex_unlock(&handshake_mtx);402 403 387 /* Already have a connection? */ 404 388 if (connected) { … … 456 440 } 457 441 458 /** Handshake with taskman459 *460 * Taskman is our spawn parent, i.e. PHONE_INITIAL is connected to it.461 * Goal of the handshake is to obtain phone to naming service and also keep the462 * session to taskman.463 *464 * @return EOK on success, for errors see taskman_handshake()465 */466 static errno_t ldr_taskman_handshake(void)467 {468 assert(session_primary == NULL);469 assert(session_taskman == NULL);470 471 errno_t retval = EOK;472 473 fibril_mutex_lock(&handshake_mtx);474 session_primary = taskman_handshake();475 if (session_primary == NULL) {476 retval = errno;477 goto finish;478 }479 480 session_taskman = async_session_primary_swap(session_primary);481 482 handshake_complete = true;483 484 finish:485 fibril_condvar_signal(&handshake_cv);486 fibril_mutex_unlock(&handshake_mtx);487 488 return retval;489 }490 491 442 /** Program loader main function. 492 443 */ … … 496 447 async_set_fallback_port_handler(ldr_connection, NULL); 497 448 498 /* Handshake with taskman */ 499 int rc = ldr_taskman_handshake(); 500 if (rc != EOK) { 501 DPRINTF("Failed taskman handshake (%i).\n", errno); 449 /* Announce to taskman. */ 450 errno_t rc = taskman_intro_loader(); 451 if (rc != EOK) { 452 printf("%s: did not receive connectin from taskman (%i)\n", 453 NAME, rc); 502 454 return rc; 503 455 } 504 456 505 /* Handle client connections */ 457 /* 458 * We are not a regular server, thus no retval is set, just wait for 459 * forwarded connections by taskman. 460 */ 506 461 async_manager(); 507 //TODO retval?508 462 509 463 /* Never reached */ -
uspace/srv/ns/ns.c
r780c8ce r012dd8e 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2015 Michal Koutny 3 4 * All rights reserved. 4 5 * … … 43 44 #include <stdio.h> 44 45 #include <errno.h> 46 #define TASKMAN_DISABLE_ASYNC 47 #include <taskman.h> 48 #undef TASKMAN_DISABLE_ASYNC 49 45 50 #include "ns.h" 46 51 #include "service.h" … … 115 120 if (rc != EOK) 116 121 return rc; 122 123 rc = taskman_intro_ns(); 124 if (rc != EOK) { 125 printf("%s: not accepted by taskman (%i)\n", NAME, rc); 126 return rc; 127 } 117 128 118 129 async_set_fallback_port_handler(ns_connection, NULL); -
uspace/srv/sysman/main.c
r780c8ce r012dd8e 229 229 fibril_add_ready(event_loop_fibril); 230 230 231 sysman_log(LVL_DEBUG, "Debugging pause...\n"); 232 async_usleep(10 * 1000000); 231 233 /* Queue first job from sequence */ 232 234 prepare_and_run_job(&target_sequence[0]); -
uspace/srv/taskman/event.c
r780c8ce r012dd8e 137 137 /* Nothing to wait for anymore */ 138 138 if (answer) { 139 async_answer_0(pr->callid, EIN VAL);139 async_answer_0(pr->callid, EINTR); 140 140 } 141 141 } else { … … 145 145 } else if (answer) { 146 146 if ((pr->flags & TASK_WAIT_BOTH) && match == TASK_WAIT_EXIT) { 147 async_answer_1(pr->callid, EINVAL, t->exit); 147 /* No sense to wait for both anymore */ 148 async_answer_1(pr->callid, EINTR, t->exit); 148 149 } else { 149 150 /* Send both exit status and retval, caller … … 253 254 pr->callid = callid; 254 255 } 255 // TODO remove printf("%s: %llu: %x, %x, %i\n", __func__, pr->id, flags, pr->flags, reuse);256 256 257 257 finish: -
uspace/srv/taskman/main.c
r780c8ce r012dd8e 41 41 #include <async.h> 42 42 #include <errno.h> 43 #include <fibril_synch.h> 43 44 #include <ipc/services.h> 44 45 #include <ipc/taskman.h> … … 53 54 #include "taskman.h" 54 55 55 // TODO move to appropriate header file56 extern async_sess_t *session_primary; 56 //#define DPRINTF(...) printf(__VA_ARGS__) 57 #define DPRINTF(...) /* empty */ 57 58 58 59 typedef struct { … … 63 64 static prodcons_t sess_queue; 64 65 66 /** We keep session to NS on our own in taskman */ 67 static async_sess_t *session_ns = NULL; 68 69 static FIBRIL_MUTEX_INITIALIZE(session_ns_mtx); 70 static FIBRIL_CONDVAR_INITIALIZE(session_ns_cv); 65 71 66 72 /* … … 69 75 static void connect_to_loader(ipc_callid_t iid, ipc_call_t *icall) 70 76 { 77 DPRINTF("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id); 71 78 /* We don't accept the connection request, we forward it instead to 72 79 * freshly spawned loader. */ … … 74 81 75 82 if (rc != EOK) { 76 printf(NAME ": %s -> %i\n", __func__, rc);77 83 async_answer_0(iid, rc); 78 84 return; … … 91 97 async_exchange_end(exch); 92 98 93 /* After forward we can dispose all session-related resources 94 * TODO later could be recycled for notification API 95 */ 99 /* After forward we can dispose all session-related resources */ 96 100 async_hangup(sess_ref->sess); 97 101 free(sess_ref); … … 105 109 } 106 110 107 static void loader_to_ns(ipc_callid_t iid, ipc_call_t *icall) 108 { 109 /* Do no accept connection request, forward it instead. */ 110 async_exch_t *exch = async_exchange_begin(session_primary); 111 static void connect_to_ns(ipc_callid_t iid, ipc_call_t *icall) 112 { 113 DPRINTF("%s, %llu\n", __func__, icall->in_task_id); 114 115 /* Wait until we know NS */ 116 fibril_mutex_lock(&session_ns_mtx); 117 while (session_ns == NULL) { 118 fibril_condvar_wait(&session_ns_cv, &session_ns_mtx); 119 } 120 fibril_mutex_unlock(&session_ns_mtx); 121 122 /* Do not accept connection, forward it */ 123 async_exch_t *exch = async_exchange_begin(session_ns); 111 124 int rc = async_forward_fast(iid, exch, 0, 0, 0, IPC_FF_NONE); 112 125 async_exchange_end(exch); … … 116 129 return; 117 130 } 131 } 132 133 static void taskman_new_task(ipc_callid_t iid, ipc_call_t *icall) 134 { 135 int rc = task_intro(icall->in_task_id); 136 async_answer_0(iid, rc); 137 } 138 139 static void taskman_i_am_ns(ipc_callid_t iid, ipc_call_t *icall) 140 { 141 DPRINTF("%s, %llu\n", __func__, icall->in_task_id); 142 int rc = EOK; 143 144 fibril_mutex_lock(&session_ns_mtx); 145 if (session_ns != NULL) { 146 rc = EEXISTS; 147 goto finish; 148 } 149 150 /* Used only for connection forwarding -- atomic */ 151 session_ns = async_callback_receive(EXCHANGE_ATOMIC); 152 153 if (session_ns == NULL) { 154 rc = ENOENT; 155 printf("%s: Cannot connect to NS\n", NAME); 156 } 157 158 fibril_condvar_signal(&session_ns_cv); 159 finish: 160 fibril_mutex_unlock(&session_ns_mtx); 161 async_answer_0(iid, rc); 118 162 } 119 163 … … 130 174 static void taskman_ctl_retval(ipc_callid_t iid, ipc_call_t *icall) 131 175 { 132 printf("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id);133 176 task_id_t sender = icall->in_task_id; 134 177 int retval = IPC_GET_ARG1(*icall); 135 178 bool wait_for_exit = IPC_GET_ARG2(*icall); 136 179 180 DPRINTF("%s:%i from %llu/%i\n", __func__, __LINE__, sender, retval); 181 137 182 int rc = task_set_retval(sender, retval, wait_for_exit); 138 183 async_answer_0(iid, rc); … … 141 186 static void taskman_ctl_ev_callback(ipc_callid_t iid, ipc_call_t *icall) 142 187 { 143 printf("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id); 188 DPRINTF("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id); 189 144 190 /* Atomic -- will be used for notifications only */ 145 191 async_sess_t *sess = async_callback_receive(EXCHANGE_ATOMIC); … … 157 203 task_id_t id = MERGE_LOUP32(IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall)); 158 204 exit_reason_t exit_reason = IPC_GET_ARG3(*icall); 159 printf("%s:%i from %llu/%i\n", __func__, __LINE__, id, exit_reason);205 DPRINTF("%s:%i from %llu/%i\n", __func__, __LINE__, id, exit_reason); 160 206 task_terminated(id, exit_reason); 161 207 } … … 164 210 { 165 211 task_id_t id = MERGE_LOUP32(IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall)); 166 printf("%s:%i from %llu\n", __func__, __LINE__, id);212 DPRINTF("%s:%i from %llu\n", __func__, __LINE__, id); 167 213 task_failed(id); 168 214 } 169 215 170 static void control_connection_loop(void)171 {172 while (true) {173 ipc_call_t call;174 ipc_callid_t callid = async_get_call(&call);175 176 if (!IPC_GET_IMETHOD(call)) {177 /* Client disconnected */178 break;179 }180 181 switch (IPC_GET_IMETHOD(call)) {182 case TASKMAN_WAIT:183 taskman_ctl_wait(callid, &call);184 break;185 case TASKMAN_RETVAL:186 taskman_ctl_retval(callid, &call);187 break;188 case TASKMAN_EVENT_CALLBACK:189 taskman_ctl_ev_callback(callid, &call);190 break;191 default:192 async_answer_0(callid, ENOENT);193 }194 }195 }196 197 static void control_connection(ipc_callid_t iid, ipc_call_t *icall)198 {199 /* TODO remove/redesign the workaround200 * Call task_intro here for boot-time tasks,201 * probably they should announce themselves explicitly202 * or taskman should detect them from kernel's list of tasks.203 */204 int rc = task_intro(icall, false);205 206 /* First, accept connection */207 async_answer_0(iid, rc);208 209 if (rc != EOK) {210 return;211 }212 213 control_connection_loop();214 }215 216 216 static void loader_callback(ipc_callid_t iid, ipc_call_t *icall) 217 217 { 218 DPRINTF("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id); 218 219 // TODO check that loader is expected, would probably discard prodcons 219 220 // scheme … … 232 233 } 233 234 234 /* Remember task_id */235 int rc = task_intro(icall, true);236 237 if (rc != EOK) {238 async_answer_0(iid, rc);239 free(sess_ref);240 return;241 }242 235 async_answer_0(iid, EOK); 243 236 … … 247 240 } 248 241 242 static bool handle_call(ipc_callid_t iid, ipc_call_t *icall) 243 { 244 switch (IPC_GET_IMETHOD(*icall)) { 245 case TASKMAN_NEW_TASK: 246 taskman_new_task(iid, icall); 247 break; 248 case TASKMAN_I_AM_NS: 249 taskman_i_am_ns(iid, icall); 250 break; 251 case TASKMAN_WAIT: 252 taskman_ctl_wait(iid, icall); 253 break; 254 case TASKMAN_RETVAL: 255 taskman_ctl_retval(iid, icall); 256 break; 257 case TASKMAN_EVENT_CALLBACK: 258 taskman_ctl_ev_callback(iid, icall); 259 break; 260 default: 261 return false; 262 } 263 return true; 264 } 265 266 static bool handle_implicit_call(ipc_callid_t iid, ipc_call_t *icall) 267 { 268 DPRINTF("%s:%i %i(%i) from %llu\n", __func__, __LINE__, 269 IPC_GET_IMETHOD(*icall), 270 IPC_GET_ARG1(*icall), 271 icall->in_task_id); 272 273 if (IPC_GET_IMETHOD(*icall) < IPC_FIRST_USER_METHOD) { 274 switch (IPC_GET_ARG1(*icall)) { 275 case TASKMAN_CONNECT_TO_NS: 276 connect_to_ns(iid, icall); 277 break; 278 case TASKMAN_CONNECT_TO_LOADER: 279 connect_to_loader(iid, icall); 280 break; 281 case TASKMAN_LOADER_CALLBACK: 282 loader_callback(iid, icall); 283 break; 284 default: 285 return false; 286 287 } 288 } else { 289 return handle_call(iid, icall); 290 } 291 292 return true; 293 } 294 295 static void implicit_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 296 { 297 if (!handle_implicit_call(iid, icall)) { 298 async_answer_0(iid, ENOTSUP); 299 return; 300 } 301 302 while (true) { 303 ipc_call_t call; 304 ipc_callid_t callid = async_get_call(&call); 305 306 if (!IPC_GET_IMETHOD(call)) { 307 /* Client disconnected */ 308 break; 309 } 310 311 if (!handle_implicit_call(callid, &call)) { 312 async_answer_0(callid, ENOTSUP); 313 break; 314 } 315 } 316 } 317 249 318 static void taskman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 250 319 { 251 taskman_interface_t iface = IPC_GET_ARG1(*icall); 252 switch (iface) { 253 case TASKMAN_CONNECT_TO_LOADER: 254 connect_to_loader(iid, icall); 255 break; 256 case TASKMAN_LOADER_TO_NS: 257 loader_to_ns(iid, icall); 258 break; 259 case TASKMAN_CONTROL: 260 control_connection(iid, icall); 261 break; 262 default: 263 /* Unknown interface */ 264 async_answer_0(iid, ENOENT); 265 } 266 } 267 268 static void implicit_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 269 { 270 taskman_interface_t iface = IPC_GET_ARG1(*icall); 271 switch (iface) { 272 case TASKMAN_LOADER_CALLBACK: 273 loader_callback(iid, icall); 274 control_connection_loop(); 275 break; 276 default: 277 /* Unknown interface on implicit connection */ 320 /* 321 * We don't expect (yet) clients to connect, having this function is 322 * just to adapt to async framework that creates new connection for 323 * each IPC_M_CONNECT_ME_TO. 324 * In this case those are to be forwarded, so don't continue 325 * "listening" on such connections. 326 */ 327 if (!handle_implicit_call(iid, icall)) { 328 /* If cannot handle connection requst, give up trying */ 278 329 async_answer_0(iid, EHANGUP); 279 } 280 } 330 return; 331 } 332 } 333 281 334 282 335 … … 298 351 rc = async_event_subscribe(EVENT_EXIT, task_exit_event, NULL); 299 352 if (rc != EOK) { 300 printf( "Cannot register for exit events (%i).\n", rc);353 printf(NAME ": Cannot register for exit events (%i).\n", rc); 301 354 return rc; 302 355 } … … 304 357 rc = async_event_subscribe(EVENT_FAULT, task_fault_event, NULL); 305 358 if (rc != EOK) { 306 printf( "Cannot register for fault events (%i).\n", rc);359 printf(NAME ": Cannot register for fault events (%i).\n", rc); 307 360 return rc; 308 361 } 309 310 /* We're service too */ 311 rc = service_register(SERVICE_TASKMAN); 312 if (rc != EOK) { 313 printf("Cannot register at naming service (%i).\n", rc); 314 return rc; 362 363 task_id_t self_id = task_get_id(); 364 rc = task_intro(self_id); 365 if (rc != EOK) { 366 printf(NAME ": Cannot register self as task (%i).\n", rc); 315 367 } 316 368 317 369 /* Start sysman server */ 370 async_set_implicit_connection(implicit_connection); 318 371 async_set_client_connection(taskman_connection); 319 async_set_implicit_connection(implicit_connection);320 372 321 373 printf(NAME ": Accepting connections\n"); 322 //TODO task_retval(EOK);374 (void)task_set_retval(self_id, EOK, false); 323 375 async_manager(); 324 376 -
uspace/srv/taskman/task.c
r780c8ce r012dd8e 109 109 } 110 110 111 int task_intro( ipc_call_t *call, bool check_unique)111 int task_intro(task_id_t id) 112 112 { 113 113 int rc = EOK; … … 115 115 fibril_rwlock_write_lock(&task_hash_table_lock); 116 116 117 task_t *t = task_get_by_id( call->in_task_id);117 task_t *t = task_get_by_id(id); 118 118 if (t != NULL) { 119 119 rc = EEXISTS; … … 130 130 * Insert into the main table. 131 131 */ 132 t->id = call->in_task_id;132 t->id = id; 133 133 t->exit = TASK_EXIT_RUNNING; 134 134 t->failed = false; -
uspace/srv/taskman/task.h
r780c8ce r012dd8e 70 70 extern task_t *task_get_by_id(task_id_t); 71 71 72 extern int task_intro( ipc_call_t *, bool);72 extern int task_intro(task_id_t); 73 73 74 74 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
