Changeset 40313e4 in mainline
- Timestamp:
- 2009-06-03T18:45:33Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bf1fb9f
- Parents:
- 5d0e461
- Location:
- uspace/srv/ns
- Files:
-
- 7 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/ns/Makefile
r5d0e461 r40313e4 42 42 OUTPUT = ns 43 43 SOURCES = \ 44 ns.c 44 ns.c \ 45 service.c \ 46 clonable.c \ 47 task.c 45 48 46 49 OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) -
uspace/srv/ns/ns.c
r5d0e461 r40313e4 36 36 */ 37 37 38 39 38 #include <ipc/ipc.h> 39 #include <ipc/services.h> 40 40 #include <ipc/ns.h> 41 #include < ipc/services.h>41 #include <unistd.h> 42 42 #include <stdio.h> 43 #include <bool.h>44 #include <unistd.h>45 #include <stdlib.h>46 43 #include <errno.h> 47 #include <assert.h> 48 #include <libadt/list.h> 49 #include <libadt/hash_table.h> 50 #include <sysinfo.h> 51 #include <loader/loader.h> 44 #include <as.h> 52 45 #include <ddi.h> 53 #include <as.h> 54 55 #define NAME "ns" 56 57 #define NS_HASH_TABLE_CHAINS 20 58 59 static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); 60 static void 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, 66 ipc_callid_t callid); 67 68 69 /* Static functions implementing NS hash table operations. */ 70 static hash_index_t ns_hash(unsigned long *key); 71 static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item); 72 static void ns_remove(link_t *item); 73 74 /** Operations for NS hash table. */ 75 static hash_table_operations_t ns_hash_table_ops = { 76 .hash = ns_hash, 77 .compare = ns_compare, 78 .remove_callback = ns_remove 79 }; 80 81 /** NS hash table structure. */ 82 static hash_table_t ns_hash_table; 83 84 /** NS hash table item. */ 85 typedef struct { 86 link_t link; 87 ipcarg_t service; /**< Number of the service. */ 88 ipcarg_t phone; /**< Phone registered with the service. */ 89 ipcarg_t in_phone_hash; /**< Incoming phone hash. */ 90 } hashed_service_t; 91 92 /** Pending connection structure. */ 93 typedef struct { 94 link_t link; 95 ipcarg_t service; /**< Number of the service. */ 96 ipc_callid_t callid; /**< Call ID waiting for the connection */ 97 ipcarg_t arg2; /**< Second argument */ 98 ipcarg_t arg3; /**< Third argument */ 99 } pending_req_t; 100 101 static link_t pending_req; 102 103 /** Request for connection to a clonable service. */ 104 typedef struct { 105 link_t link; 106 ipcarg_t service; 107 ipc_call_t call; 108 ipc_callid_t callid; 109 } cs_req_t; 110 111 /** List of clonable-service connection requests. */ 112 static link_t cs_req; 46 #include <event.h> 47 #include <macros.h> 48 #include "ns.h" 49 #include "service.h" 50 #include "clonable.h" 51 #include "task.h" 113 52 114 53 static void *clockaddr = NULL; 115 54 static void *klogaddr = NULL; 116 55 117 /** Return true if @a service is clonable. */ 118 static bool service_clonable(int service) 119 { 120 return (service == SERVICE_LOAD); 121 } 122 123 static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr, count_t pages, void **addr) 56 static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr, 57 size_t pages, void **addr) 124 58 { 125 59 if (ph_addr == NULL) { … … 146 80 } 147 81 148 /** Process pending connection requests */149 static void process_pending_req()150 {151 link_t *cur;152 153 loop:154 for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {155 pending_req_t *pr = list_get_instance(cur, pending_req_t, link);156 157 unsigned long keys[3] = {158 pr->service,159 0,160 0161 };162 163 link_t *link = hash_table_find(&ns_hash_table, keys);164 if (!link)165 continue;166 167 hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);168 ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,169 pr->arg2, pr->arg3, 0, IPC_FF_NONE);170 171 if (!(pr->callid & IPC_CALLID_NOTIFICATION))172 ipc_answer_0(pr->callid, retval);173 174 list_remove(cur);175 free(pr);176 goto loop;177 }178 }179 180 82 int main(int argc, char **argv) 181 83 { 182 84 printf(NAME ": HelenOS IPC Naming Service\n"); 183 85 184 if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, 185 &ns_hash_table_ops)) { 186 printf(NAME ": No memory available for services\n"); 187 return ENOMEM; 188 } 86 int rc = service_init(); 87 if (rc != EOK) 88 return rc; 189 89 190 list_initialize(&pending_req); 191 list_initialize(&cs_req); 90 rc = clonable_init(); 91 if (rc != EOK) 92 return rc; 93 94 rc = task_init(); 95 if (rc != EOK) 96 return rc; 192 97 193 98 printf(NAME ": Accepting connections\n"); 99 194 100 while (true) { 195 process_pending_req(); 101 process_pending_conn(); 102 process_pending_wait(); 196 103 197 104 ipc_call_t call; 198 105 ipc_callid_t callid = ipc_wait_for_call(&call); 106 107 task_id_t id; 199 108 ipcarg_t retval; 109 110 if (callid & IPC_CALLID_NOTIFICATION) { 111 id = (task_id_t) 112 MERGE_LOUP32(IPC_GET_ARG2(call), IPC_GET_ARG3(call)); 113 wait_notification((wait_type_t) IPC_GET_ARG1(call), id); 114 continue; 115 } 200 116 201 117 switch (IPC_GET_METHOD(call)) { … … 203 119 switch (IPC_GET_ARG3(call)) { 204 120 case SERVICE_MEM_REALTIME: 205 get_as_area(callid, &call, sysinfo_value("clock.faddr"), 1, &clockaddr); 121 get_as_area(callid, &call, 122 (void *) sysinfo_value("clock.faddr"), 123 1, &clockaddr); 206 124 break; 207 125 case SERVICE_MEM_KLOG: 208 get_as_area(callid, &call, sysinfo_value("klog.faddr"), sysinfo_value("klog.pages"), &klogaddr); 126 get_as_area(callid, &call, 127 (void *) sysinfo_value("klog.faddr"), 128 sysinfo_value("klog.pages"), &klogaddr); 209 129 break; 210 130 default: … … 242 162 } 243 163 break; 164 case NS_PING: 165 retval = EOK; 166 break; 167 case NS_TASK_WAIT: 168 id = (task_id_t) 169 MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 170 wait_for_task(id, &call, callid); 171 continue; 244 172 default: 245 173 retval = ENOENT; … … 255 183 } 256 184 257 /** Register service.258 *259 * @param service Service to be registered.260 * @param phone Phone to be used for connections to the service.261 * @param call Pointer to call structure.262 *263 * @return Zero on success or a value from @ref errno.h.264 *265 */266 int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)267 {268 unsigned long keys[3] = {269 service,270 call->in_phone_hash,271 0272 };273 274 if (hash_table_find(&ns_hash_table, keys))275 return EEXISTS;276 277 hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));278 if (!hs)279 return ENOMEM;280 281 link_initialize(&hs->link);282 hs->service = service;283 hs->phone = phone;284 hs->in_phone_hash = call->in_phone_hash;285 hash_table_insert(&ns_hash_table, keys, &hs->link);286 287 return 0;288 }289 290 /** Connect client to service.291 *292 * @param service Service to be connected to.293 * @param call Pointer to call structure.294 * @param callid Call ID of the request.295 *296 * @return Zero on success or a value from @ref errno.h.297 *298 */299 void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)300 {301 ipcarg_t retval;302 unsigned long keys[3] = {303 service,304 0,305 0306 };307 308 link_t *link = hash_table_find(&ns_hash_table, keys);309 if (!link) {310 if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {311 /* Blocking connection, add to pending list */312 pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));313 if (!pr) {314 retval = ENOMEM;315 goto out;316 }317 318 pr->service = service;319 pr->callid = callid;320 pr->arg2 = IPC_GET_ARG2(*call);321 pr->arg3 = IPC_GET_ARG3(*call);322 list_append(&pr->link, &pending_req);323 return;324 }325 retval = ENOENT;326 goto out;327 }328 329 hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);330 retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),331 IPC_GET_ARG3(*call), 0, IPC_FF_NONE);332 out:333 if (!(callid & IPC_CALLID_NOTIFICATION))334 ipc_answer_0(callid, retval);335 }336 337 /** Register clonable service.338 *339 * @param service Service to be registered.340 * @param phone Phone to be used for connections to the service.341 * @param call Pointer to call structure.342 *343 */344 void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,345 ipc_callid_t callid)346 {347 if (list_empty(&cs_req)) {348 /* There was no pending connection request. */349 printf(NAME ": Unexpected clonable server.\n");350 ipc_answer_0(callid, EBUSY);351 return;352 }353 354 cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);355 list_remove(&csr->link);356 357 /* Currently we can only handle a single type of clonable service. */358 assert(csr->service == SERVICE_LOAD);359 360 ipc_answer_0(callid, EOK);361 362 int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),363 IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);364 365 free(csr);366 ipc_hangup(phone);367 }368 369 /** Connect client to clonable service.370 *371 * @param service Service to be connected to.372 * @param call Pointer to call structure.373 * @param callid Call ID of the request.374 *375 * @return Zero on success or a value from @ref errno.h.376 *377 */378 void connect_to_clonable(ipcarg_t service, ipc_call_t *call,379 ipc_callid_t callid)380 {381 assert(service == SERVICE_LOAD);382 383 cs_req_t *csr = malloc(sizeof(cs_req_t));384 if (csr == NULL) {385 ipc_answer_0(callid, ENOMEM);386 return;387 }388 389 /* Spawn a loader. */390 int rc = loader_spawn("loader");391 392 if (rc < 0) {393 free(csr);394 ipc_answer_0(callid, rc);395 return;396 }397 398 csr->service = service;399 csr->call = *call;400 csr->callid = callid;401 402 /*403 * We can forward the call only after the server we spawned connects404 * to us. Meanwhile we might need to service more connection requests.405 * Thus we store the call in a queue.406 */407 list_append(&csr->link, &cs_req);408 }409 410 /** Compute hash index into NS hash table.411 *412 * @param key Pointer keys. However, only the first key (i.e. service number)413 * is used to compute the hash index.414 *415 * @return Hash index corresponding to key[0].416 *417 */418 hash_index_t ns_hash(unsigned long *key)419 {420 assert(key);421 return (*key % NS_HASH_TABLE_CHAINS);422 }423 424 /** Compare a key with hashed item.425 *426 * This compare function always ignores the third key.427 * It exists only to make it possible to remove records428 * originating from connection with key[1] in_phone_hash429 * value. Note that this is close to being classified430 * as a nasty hack.431 *432 * @param key Array of keys.433 * @param keys Must be lesser or equal to 3.434 * @param item Pointer to a hash table item.435 *436 * @return Non-zero if the key matches the item, zero otherwise.437 *438 */439 int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)440 {441 assert(key);442 assert(keys <= 3);443 assert(item);444 445 hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);446 447 if (keys == 2)448 return key[1] == hs->in_phone_hash;449 else450 return key[0] == hs->service;451 }452 453 /** Perform actions after removal of item from the hash table.454 *455 * @param item Item that was removed from the hash table.456 *457 */458 void ns_remove(link_t *item)459 {460 assert(item);461 free(hash_table_get_instance(item, hashed_service_t, link));462 }463 464 185 /** 465 186 * @}
Note:
See TracChangeset
for help on using the changeset viewer.