Changeset 1fcfc94 in mainline
- Timestamp:
- 2009-03-02T17:35:03Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6519d6f
- Parents:
- a32c9bb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/ns/ns.c
ra32c9bb r1fcfc94 29 29 /** @addtogroup ns 30 30 * @{ 31 */ 31 */ 32 32 33 33 /** 34 * @file 35 * @brief 34 * @file ns.c 35 * @brief Naming service for HelenOS IPC. 36 36 */ 37 37 … … 53 53 #include <as.h> 54 54 55 #define NAME 56 57 #define NS_HASH_TABLE_CHAINS 55 #define NAME "ns" 56 57 #define NS_HASH_TABLE_CHAINS 20 58 58 59 59 static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); 60 static intconnect_to_service(ipcarg_t service, ipc_call_t *call,60 static void connect_to_service(ipcarg_t service, ipc_call_t *call, 61 61 ipc_callid_t callid); 62 62 … … 65 65 void connect_to_clonable(ipcarg_t service, ipc_call_t *call, 66 66 ipc_callid_t callid); 67 67 68 68 69 /* Static functions implementing NS hash table operations. */ … … 84 85 typedef struct { 85 86 link_t link; 86 ipcarg_t service; 87 ipcarg_t phone; 88 ipcarg_t in_phone_hash; 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. */ 89 90 } hashed_service_t; 90 91 91 static void *clockaddr = NULL; 92 static void *klogaddr = NULL; 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; 93 102 94 103 /** Request for connection to a clonable service. */ … … 103 112 static link_t cs_req; 104 113 114 static void *clockaddr = NULL; 115 static void *klogaddr = NULL; 116 105 117 /** Return true if @a service is clonable. */ 106 118 static bool service_clonable(int service) 107 119 { 108 return service == SERVICE_LOAD;120 return (service == SERVICE_LOAD); 109 121 } 110 122 … … 129 141 } 130 142 143 /** Process pending connection requests */ 144 static void process_pending_req() 145 { 146 link_t *cur; 147 148 loop: 149 for (cur = pending_req.next; cur != &pending_req; cur = cur->next) { 150 pending_req_t *pr = list_get_instance(cur, pending_req_t, link); 151 152 unsigned long keys[3] = { 153 pr->service, 154 0, 155 0 156 }; 157 158 link_t *link = hash_table_find(&ns_hash_table, keys); 159 if (!link) 160 continue; 161 162 hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link); 163 ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone, 164 pr->arg2, pr->arg3, 0, IPC_FF_NONE); 165 166 if (!(pr->callid & IPC_CALLID_NOTIFICATION)) 167 ipc_answer_0(pr->callid, retval); 168 169 list_remove(cur); 170 free(pr); 171 goto loop; 172 } 173 } 174 131 175 int main(int argc, char **argv) 132 176 { 133 177 printf(NAME ": HelenOS IPC Naming Service\n"); 134 178 135 ipc_call_t call;136 ipc_callid_t callid;137 138 ipcarg_t retval;139 140 179 if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, 141 180 &ns_hash_table_ops)) { 142 printf(NAME ": No memory available \n");181 printf(NAME ": No memory available for services\n"); 143 182 return ENOMEM; 144 183 } 145 184 185 list_initialize(&pending_req); 146 186 list_initialize(&cs_req); 147 187 148 188 printf(NAME ": Accepting connections\n"); 149 while (1) { 150 callid = ipc_wait_for_call(&call); 189 while (true) { 190 process_pending_req(); 191 192 ipc_call_t call; 193 ipc_callid_t callid = ipc_wait_for_call(&call); 194 ipcarg_t retval; 195 151 196 switch (IPC_GET_METHOD(call)) { 152 197 case IPC_M_SHARE_IN: … … 187 232 continue; 188 233 } else { 189 retval = connect_to_service(IPC_GET_ARG1(call), 190 &call, callid); 234 connect_to_service(IPC_GET_ARG1(call), &call, 235 callid); 236 continue; 191 237 } 192 238 break; … … 195 241 break; 196 242 } 197 if (!(callid & IPC_CALLID_NOTIFICATION)) { 243 244 if (!(callid & IPC_CALLID_NOTIFICATION)) 198 245 ipc_answer_0(callid, retval); 199 }200 246 } 201 247 … … 206 252 /** Register service. 207 253 * 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. 254 * @param service Service to be registered. 255 * @param phone Phone to be used for connections to the service. 256 * @param call Pointer to call structure. 257 * 258 * @return Zero on success or a value from @ref errno.h. 259 * 213 260 */ 214 261 int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call) … … 219 266 0 220 267 }; 221 hashed_service_t *hs; 222 223 if (hash_table_find(&ns_hash_table, keys)) { 268 269 if (hash_table_find(&ns_hash_table, keys)) 224 270 return EEXISTS; 225 } 226 227 hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); 228 if (!hs) { 271 272 hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); 273 if (!hs) 229 274 return ENOMEM; 230 } 231 275 232 276 link_initialize(&hs->link); 233 277 hs->service = service; … … 235 279 hs->in_phone_hash = call->in_phone_hash; 236 280 hash_table_insert(&ns_hash_table, keys, &hs->link); 281 282 return 0; 283 } 284 285 /** Connect client to service. 286 * 287 * @param service Service to be connected to. 288 * @param call Pointer to call structure. 289 * @param callid Call ID of the request. 290 * 291 * @return Zero on success or a value from @ref errno.h. 292 * 293 */ 294 void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) 295 { 296 ipcarg_t retval; 297 unsigned long keys[3] = { 298 service, 299 0, 300 0 301 }; 302 303 link_t *link = hash_table_find(&ns_hash_table, keys); 304 if (!link) { 305 if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) { 306 /* Blocking connection, add to pending list */ 307 pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); 308 if (!pr) { 309 retval = ENOMEM; 310 goto out; 311 } 237 312 238 return 0; 239 } 240 241 /** Connect client to service. 242 * 243 * @param service Service to be connected to. 244 * @param call Pointer to call structure. 245 * @param callid Call ID of the request. 246 * 247 * @return Zero on success or a value from @ref errno.h. 248 */ 249 int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) 250 { 251 unsigned long keys[3] = { service, 0, 0 }; 252 link_t *hlp; 253 hashed_service_t *hs; 254 255 hlp = hash_table_find(&ns_hash_table, keys); 256 if (!hlp) { 257 return ENOENT; 258 } 259 hs = hash_table_get_instance(hlp, hashed_service_t, link); 260 return ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), 261 IPC_GET_ARG3(*call), 0, IPC_FF_NONE); 313 pr->service = service; 314 pr->callid = callid; 315 pr->arg2 = IPC_GET_ARG2(*call); 316 pr->arg3 = IPC_GET_ARG3(*call); 317 list_append(&pr->link, &pending_req); 318 return; 319 } 320 retval = ENOENT; 321 goto out; 322 } 323 324 hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link); 325 retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call), 326 IPC_GET_ARG3(*call), 0, IPC_FF_NONE); 327 328 out: 329 if (!(callid & IPC_CALLID_NOTIFICATION)) 330 ipc_answer_0(callid, retval); 262 331 } 263 332 264 333 /** Register clonable service. 265 334 * 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. 335 * @param service Service to be registered. 336 * @param phone Phone to be used for connections to the service. 337 * @param call Pointer to call structure. 338 * 269 339 */ 270 340 void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call, 271 341 ipc_callid_t callid) 272 342 { 273 int rc;274 cs_req_t *csr;275 276 343 if (list_empty(&cs_req)) { 277 344 /* There was no pending connection request. */ … … 280 347 return; 281 348 } 282 283 cs r = list_get_instance(cs_req.next, cs_req_t, link);349 350 cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link); 284 351 list_remove(&csr->link); 285 352 286 353 /* Currently we can only handle a single type of clonable service. */ 287 354 assert(csr->service == SERVICE_LOAD); 288 355 289 356 ipc_answer_0(callid, EOK); 290 291 rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),357 358 int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call), 292 359 IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE); 293 360 294 361 free(csr); 295 362 } … … 297 364 /** Connect client to clonable service. 298 365 * 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. 366 * @param service Service to be connected to. 367 * @param call Pointer to call structure. 368 * @param callid Call ID of the request. 369 * 370 * @return Zero on success or a value from @ref errno.h. 371 * 304 372 */ 305 373 void connect_to_clonable(ipcarg_t service, ipc_call_t *call, 306 374 ipc_callid_t callid) 307 375 { 308 int rc;309 cs_req_t *csr;310 311 376 assert(service == SERVICE_LOAD); 312 313 cs r = malloc(sizeof(cs_req_t));377 378 cs_req_t *csr = malloc(sizeof(cs_req_t)); 314 379 if (csr == NULL) { 315 380 ipc_answer_0(callid, ENOMEM); 316 381 return; 317 382 } 318 383 319 384 /* Spawn a loader. */ 320 rc = loader_spawn("loader");321 385 int rc = loader_spawn("loader"); 386 322 387 if (rc < 0) { 323 388 free(csr); … … 325 390 return; 326 391 } 327 392 328 393 csr->service = service; 329 394 csr->call = *call; 330 395 csr->callid = callid; 331 396 332 397 /* 333 398 * We can forward the call only after the server we spawned connects … … 341 406 * 342 407 * @param key Pointer keys. However, only the first key (i.e. service number) 343 * is used to compute the hash index. 408 * is used to compute the hash index. 409 * 344 410 * @return Hash index corresponding to key[0]. 411 * 345 412 */ 346 413 hash_index_t ns_hash(unsigned long *key) 347 414 { 348 415 assert(key); 349 return *key % NS_HASH_TABLE_CHAINS;416 return (*key % NS_HASH_TABLE_CHAINS); 350 417 } 351 418 … … 358 425 * as a nasty hack. 359 426 * 360 * @param key Array of keys.427 * @param key Array of keys. 361 428 * @param keys Must be lesser or equal to 3. 362 429 * @param item Pointer to a hash table item. 430 * 363 431 * @return Non-zero if the key matches the item, zero otherwise. 432 * 364 433 */ 365 434 int ns_compare(unsigned long key[], hash_count_t keys, link_t *item) 366 435 { 367 hashed_service_t *hs;368 369 436 assert(key); 370 437 assert(keys <= 3); 371 438 assert(item); 372 439 373 h s = hash_table_get_instance(item, hashed_service_t, link);440 hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link); 374 441 375 442 if (keys == 2) … … 382 449 * 383 450 * @param item Item that was removed from the hash table. 451 * 384 452 */ 385 453 void ns_remove(link_t *item) … … 389 457 } 390 458 391 /** 459 /** 392 460 * @} 393 461 */
Note:
See TracChangeset
for help on using the changeset viewer.