Changeset bfd1546 in mainline
- Timestamp:
- 2009-02-15T00:01:06Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 08b777e
- Parents:
- 4cac212c
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/proc/program.h
r4cac212c rbfd1546 60 60 extern void program_ready(program_t *p); 61 61 62 extern unative_t sys_program_spawn_loader(int *uspace_phone_id, 63 char *uspace_name, size_t name_len); 62 extern unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len); 64 63 65 64 #endif -
kernel/generic/src/proc/program.c
r4cac212c rbfd1546 191 191 /** Syscall for creating a new loader instance from userspace. 192 192 * 193 * Creates a new task from the program loader image, connects a phone 194 * to it and stores the phone id into the provided buffer. 195 * 196 * @param uspace_phone_id Userspace address where to store the phone id. 193 * Creates a new task from the program loader image and sets 194 * the task name. 195 * 197 196 * @param name Name to set on the new task (typically the same 198 197 * as the command used to execute it). … … 200 199 * @return 0 on success or an error code from @ref errno.h. 201 200 */ 202 unative_t sys_program_spawn_loader(int *uspace_phone_id, char *uspace_name, 203 size_t name_len) 201 unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len) 204 202 { 205 203 program_t p; 206 int fake_id;207 204 int rc; 208 int phone_id;209 205 char namebuf[TASK_NAME_BUFLEN]; 210 211 fake_id = 0;212 213 /* Before we even try creating the task, see if we can write the id */214 rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id,215 sizeof(fake_id));216 if (rc != 0)217 return rc;218 206 219 207 /* Cap length of name and copy it from userspace. */ … … 228 216 namebuf[name_len] = '\0'; 229 217 230 /* Allocate the phone for communicating with the new task. */231 232 phone_id = phone_alloc();233 if (phone_id < 0)234 return ELIMIT;235 236 218 /* Spawn the new task. */ 237 219 … … 240 222 return rc; 241 223 242 phone_connect(phone_id, &p.task->answerbox);243 244 /* No need to aquire lock before task_ready() */245 rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id,246 sizeof(phone_id));247 if (rc != 0) {248 /* Ooops */249 ipc_phone_hangup(&TASK->phones[phone_id]);250 task_kill(p.task->taskid);251 return rc;252 }253 254 224 // FIXME: control the capabilities 255 225 cap_set(p.task, cap_get(TASK)); -
uspace/lib/libc/generic/loader.c
r4cac212c rbfd1546 35 35 #include <ipc/ipc.h> 36 36 #include <ipc/loader.h> 37 #include <ipc/services.h> 37 38 #include <libc.h> 38 39 #include <task.h> … … 51 52 * de-allocated using free() after use). 52 53 */ 53 loader_t *loader_spawn(const char *name) 54 { 55 int phone_id, rc; 54 int loader_spawn(const char *name) 55 { 56 return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER, 57 (sysarg_t) name, strlen(name)); 58 } 59 60 loader_t *loader_connect(void) 61 { 56 62 loader_t *ldr; 57 58 /* 59 * Ask kernel to spawn a new loader task. 60 */ 61 rc = __SYSCALL3(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id, 62 (sysarg_t) name, strlen(name)); 63 if (rc != 0) 64 return NULL; 65 66 /* 67 * Say hello so that the loader knows the incoming connection's 68 * phone hash. 69 */ 70 rc = async_req_0_0(phone_id, LOADER_HELLO); 71 if (rc != EOK) 63 int phone_id; 64 65 phone_id = ipc_connect_me_to(PHONE_NS, SERVICE_LOAD, 0, 0); 66 if (phone_id < 0) 72 67 return NULL; 73 68 … … 77 72 78 73 ldr->phone_id = phone_id; 79 return ldr; 74 return ldr; 80 75 } 81 76 -
uspace/lib/libc/generic/task.c
r4cac212c rbfd1546 64 64 int rc; 65 65 66 /* Spawn a program loader. */67 ldr = loader_ spawn(path);66 /* Connect to a program loader. */ 67 ldr = loader_connect(); 68 68 if (ldr == NULL) 69 69 return 0; … … 90 90 91 91 /* Run it. */ 92 /* Load the program. */93 92 rc = loader_run(ldr); 94 93 if (rc != EOK) -
uspace/lib/libc/include/ipc/services.h
r4cac212c rbfd1546 39 39 40 40 typedef enum { 41 SERVICE_PCI = 1, 41 SERVICE_LOAD = 1, 42 SERVICE_PCI, 42 43 SERVICE_KEYBOARD, 43 44 SERVICE_VIDEO, -
uspace/lib/libc/include/loader/loader.h
r4cac212c rbfd1546 45 45 } loader_t; 46 46 47 extern loader_t *loader_spawn(const char *name); 47 extern int loader_spawn(const char *); 48 extern loader_t *loader_connect(void); 48 49 extern int loader_get_task_id(loader_t *, task_id_t *); 49 50 extern int loader_set_pathname(loader_t *, const char *); -
uspace/srv/loader/main.c
r4cac212c rbfd1546 51 51 #include <sys/types.h> 52 52 #include <ipc/ipc.h> 53 #include <ipc/services.h> 53 54 #include <ipc/loader.h> 54 55 #include <loader/pcb.h> … … 80 81 static bool is_dyn_linked; 81 82 83 /** Used to limit number of connections to one. */ 84 static bool connected; 82 85 83 86 static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request) … … 297 300 ipc_call_t call; 298 301 int retval; 302 303 /* Already have a connection? */ 304 if (connected) { 305 ipc_answer_0(iid, ELIMIT); 306 return; 307 } 308 309 connected = true; 310 311 /* Accept the connection */ 312 ipc_answer_0(iid, EOK); 299 313 300 314 /* Ignore parameters, the connection is already open */ … … 339 353 int main(int argc, char *argv[]) 340 354 { 341 ipc_callid_t callid; 342 ipc_call_t call; 343 ipcarg_t phone_hash; 344 345 /* The first call only communicates the incoming phone hash */ 346 callid = ipc_wait_for_call(&call); 347 348 if (IPC_GET_METHOD(call) != LOADER_HELLO) { 349 if (IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) 350 ipc_answer_0(callid, EINVAL); 351 return 1; 352 } 353 354 ipc_answer_0(callid, EOK); 355 phone_hash = call.in_phone_hash; 356 357 /* 358 * Up until now async must not be used as it couldn't 359 * handle incoming requests. (Which means e.g. printf() 360 * cannot be used) 361 */ 362 async_new_connection(phone_hash, 0, NULL, loader_connection); 355 ipcarg_t phonead; 356 357 connected = false; 358 359 /* Set a handler of incomming connections. */ 360 async_set_client_connection(loader_connection); 361 362 /* Register at naming service. */ 363 if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0) 364 return -1; 365 363 366 async_manager(); 364 367 365 /* notreached */368 /* Never reached */ 366 369 return 0; 367 370 } -
uspace/srv/ns/ns.c
r4cac212c rbfd1546 41 41 #include <ipc/services.h> 42 42 #include <stdio.h> 43 #include <bool.h> 43 44 #include <unistd.h> 44 45 #include <stdlib.h> … … 48 49 #include <libadt/hash_table.h> 49 50 #include <sysinfo.h> 51 #include <loader/loader.h> 50 52 #include <ddi.h> 51 53 #include <as.h> … … 57 59 static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); 58 60 static int connect_to_service(ipcarg_t service, ipc_call_t *call, 61 ipc_callid_t callid); 62 63 void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call, 64 ipc_callid_t callid); 65 void connect_to_clonable(ipcarg_t service, ipc_call_t *call, 59 66 ipc_callid_t callid); 60 67 … … 84 91 static void *clockaddr = NULL; 85 92 static void *klogaddr = NULL; 93 94 /** Request for connection to a clonable service. */ 95 typedef struct { 96 link_t link; 97 ipcarg_t service; 98 ipc_call_t *call; 99 ipc_callid_t callid; 100 } cs_req_t; 101 102 /** List of clonable-service connection requests. */ 103 static link_t cs_req; 104 105 /** Return true if @a service is clonable. */ 106 static bool service_clonable(int service) 107 { 108 return service == SERVICE_LOAD; 109 } 86 110 87 111 static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, … … 117 141 return ENOMEM; 118 142 } 143 144 list_initialize(&cs_req); 119 145 120 146 printf(NAME ": Accepting connections\n"); … … 143 169 * Server requests service registration. 144 170 */ 145 retval = register_service(IPC_GET_ARG1(call), 146 IPC_GET_ARG5(call), &call); 171 if (service_clonable(IPC_GET_ARG1(call))) { 172 register_clonable(IPC_GET_ARG1(call), 173 IPC_GET_ARG5(call), &call, callid); 174 continue; 175 } else { 176 retval = register_service(IPC_GET_ARG1(call), 177 IPC_GET_ARG5(call), &call); 178 } 147 179 break; 148 180 case IPC_M_CONNECT_ME_TO: … … 150 182 * Client requests to be connected to a service. 151 183 */ 152 retval = connect_to_service(IPC_GET_ARG1(call), &call, 153 callid); 184 if (service_clonable(IPC_GET_ARG1(call))) { 185 connect_to_clonable(IPC_GET_ARG1(call), 186 &call, callid); 187 continue; 188 } else { 189 retval = connect_to_service(IPC_GET_ARG1(call), 190 &call, callid); 191 } 154 192 break; 155 193 default: … … 168 206 /** Register service. 169 207 * 170 * @param service 171 * @param phone 172 * @param call 173 * 174 * @return 208 * @param service Service to be registered. 209 * @param phone Phone to be used for connections to the service. 210 * @param call Pointer to call structure. 211 * 212 * @return Zero on success or a value from @ref errno.h. 175 213 */ 176 214 int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call) … … 182 220 }; 183 221 hashed_service_t *hs; 184 222 185 223 if (hash_table_find(&ns_hash_table, keys)) { 186 224 return EEXISTS; … … 203 241 /** Connect client to service. 204 242 * 205 * @param service 206 * @param call 207 * @param callid 243 * @param service Service to be connected to. 244 * @param call Pointer to call structure. 245 * @param callid Call ID of the request. 208 246 * 209 247 * @return Zero on success or a value from @ref errno.h. … … 214 252 link_t *hlp; 215 253 hashed_service_t *hs; 216 254 217 255 hlp = hash_table_find(&ns_hash_table, keys); 218 256 if (!hlp) { … … 222 260 return ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), 223 261 IPC_GET_ARG3(*call), 0, IPC_FF_NONE); 262 } 263 264 /** Register clonable service. 265 * 266 * @param service Service to be registered. 267 * @param phone Phone to be used for connections to the service. 268 * @param call Pointer to call structure. 269 */ 270 void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call, 271 ipc_callid_t callid) 272 { 273 int rc; 274 cs_req_t *csr; 275 276 if (list_empty(&cs_req)) { 277 /* There was no pending connection request. */ 278 printf(NAME ": Unexpected clonable server.\n"); 279 ipc_answer_0(callid, EBUSY); 280 return; 281 } 282 283 csr = list_get_instance(cs_req.next, cs_req_t, link); 284 list_remove(&csr->link); 285 286 /* Currently we can only handle a single type of clonable service. */ 287 assert(csr->service == SERVICE_LOAD); 288 289 ipc_answer_0(callid, EOK); 290 291 rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(*csr->call), 292 IPC_GET_ARG3(*csr->call), 0, IPC_FF_NONE); 293 294 free(csr); 295 } 296 297 /** Connect client to clonable service. 298 * 299 * @param service Service to be connected to. 300 * @param call Pointer to call structure. 301 * @param callid Call ID of the request. 302 * 303 * @return Zero on success or a value from @ref errno.h. 304 */ 305 void connect_to_clonable(ipcarg_t service, ipc_call_t *call, 306 ipc_callid_t callid) 307 { 308 int rc; 309 cs_req_t *csr; 310 311 assert(service == SERVICE_LOAD); 312 313 csr = malloc(sizeof(cs_req_t)); 314 if (csr == NULL) { 315 ipc_answer_0(callid, ENOMEM); 316 return; 317 } 318 319 /* Spawn a loader. */ 320 rc = loader_spawn("loader"); 321 322 if (rc < 0) { 323 free(csr); 324 ipc_answer_0(callid, rc); 325 return; 326 } 327 328 csr->service = service; 329 csr->call = call; 330 csr->callid = callid; 331 332 /* 333 * We can forward the call only after the server we spawned connects 334 * to us. Meanwhile we might need to service more connection requests. 335 * Thus we store the call in a queue. 336 */ 337 list_append(&csr->link, &cs_req); 224 338 } 225 339
Note:
See TracChangeset
for help on using the changeset viewer.