Changeset 012dd8e in mainline for uspace/srv/taskman/main.c
- Timestamp:
- 2019-08-07T09:15:30Z (5 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.