ns.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Ondrej Palkovsky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00039 #include <ipc/ipc.h>
00040 #include <ipc/ns.h>
00041 #include <ipc/services.h>
00042 #include <stdio.h>
00043 #include <unistd.h>
00044 #include <stdlib.h>
00045 #include <errno.h>
00046 #include <assert.h>
00047 #include <libadt/list.h>
00048 #include <libadt/hash_table.h>
00049 #include <sysinfo.h>
00050 #include <ddi.h>
00051 #include <as.h>
00052 
00053 #define NAME    "NS"
00054 
00055 #define NS_HASH_TABLE_CHAINS    20
00056 
00057 static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
00058 static int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid);
00059 
00060 /* Static functions implementing NS hash table operations. */
00061 static hash_index_t ns_hash(unsigned long *key);
00062 static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
00063 static void ns_remove(link_t *item);
00064 
00066 static hash_table_operations_t ns_hash_table_ops = {
00067         .hash = ns_hash,
00068         .compare = ns_compare,
00069         .remove_callback = ns_remove
00070 };
00071 
00073 static hash_table_t ns_hash_table;
00074 
00076 typedef struct {
00077         link_t link;
00078         ipcarg_t service;               
00079         ipcarg_t phone;                 
00080         ipcarg_t in_phone_hash;         
00081 } hashed_service_t;
00082 
00083 static void *clockaddr = NULL;
00084 static void *klogaddr = NULL;
00085 
00086 static void get_as(ipc_callid_t callid, ipc_call_t *call, char *name, void **addr)
00087 {
00088         void *ph_addr;
00089 
00090         if (!*addr) {
00091                 ph_addr = (void *)sysinfo_value(name);
00092                 if (!ph_addr) {
00093                         ipc_answer_fast(callid, ENOENT, 0, 0);
00094                         return;
00095                 }
00096                 *addr = as_get_mappable_page(PAGE_SIZE);
00097                 map_physmem(ph_addr, *addr, 1, AS_AREA_READ | AS_AREA_CACHEABLE);
00098         }
00099         ipc_answer_fast(callid, 0, (ipcarg_t)*addr, AS_AREA_READ);
00100 }
00101 
00102 int main(int argc, char **argv)
00103 {
00104         ipc_call_t call;
00105         ipc_callid_t callid;
00106         
00107         ipcarg_t retval;
00108 
00109         if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, &ns_hash_table_ops)) {
00110                 return ENOMEM;
00111         }
00112                 
00113         while (1) {
00114                 callid = ipc_wait_for_call(&call);
00115                 switch (IPC_GET_METHOD(call)) {
00116                 case IPC_M_AS_AREA_RECV:
00117                         switch (IPC_GET_ARG3(call)) {
00118                         case SERVICE_MEM_REALTIME:
00119                                 get_as(callid, &call, "clock.faddr", &clockaddr);
00120                                 break;
00121                         case SERVICE_MEM_KLOG:
00122                                 get_as(callid, &call, "klog.faddr", &klogaddr);
00123                                 break;
00124                         default:
00125                                 ipc_answer_fast(callid, ENOENT, 0, 0);
00126                         }
00127                         continue;
00128                 case IPC_M_PHONE_HUNGUP:
00129                         retval = 0;
00130                         break;
00131                 case IPC_M_CONNECT_TO_ME:
00132                         /*
00133                          * Server requests service registration.
00134                          */
00135                         retval = register_service(IPC_GET_ARG1(call), IPC_GET_ARG3(call), &call);
00136                         break;
00137                 case IPC_M_CONNECT_ME_TO:
00138                         /*
00139                          * Client requests to be connected to a service.
00140                          */
00141                         retval = connect_to_service(IPC_GET_ARG1(call), &call, callid);
00142                         break;
00143                 default:
00144                         retval = ENOENT;
00145                         break;
00146                 }
00147                 if (! (callid & IPC_CALLID_NOTIFICATION)) {
00148                         ipc_answer_fast(callid, retval, 0, 0);
00149                 }
00150         }
00151 }
00152 
00161 int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
00162 {
00163         unsigned long keys[3] = { service, call->in_phone_hash, 0 };
00164         hashed_service_t *hs;
00165                         
00166         if (hash_table_find(&ns_hash_table, keys)) {
00167                 return EEXISTS;
00168         }
00169                         
00170         hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
00171         if (!hs) {
00172                 return ENOMEM;
00173         }
00174                         
00175         link_initialize(&hs->link);
00176         hs->service = service;
00177         hs->phone = phone;
00178         hs->in_phone_hash = call->in_phone_hash;
00179         hash_table_insert(&ns_hash_table, keys, &hs->link);
00180                         
00181         return 0;
00182 }
00183 
00192 int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
00193 {
00194         unsigned long keys[3] = { service, 0, 0 };
00195         link_t *hlp;
00196         hashed_service_t *hs;
00197                         
00198         hlp = hash_table_find(&ns_hash_table, keys);
00199         if (!hlp) {
00200                 return ENOENT;
00201         }
00202         hs = hash_table_get_instance(hlp, hashed_service_t, link);
00203         return ipc_forward_fast(callid, hs->phone, 0, 0);
00204 }
00205 
00212 hash_index_t ns_hash(unsigned long *key)
00213 {
00214         assert(key);
00215         return *key % NS_HASH_TABLE_CHAINS;
00216 }
00217 
00231 int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
00232 {
00233         hashed_service_t *hs;
00234 
00235         assert(key);
00236         assert(keys <= 3);
00237         assert(item);
00238         
00239         hs = hash_table_get_instance(item, hashed_service_t, link);
00240         
00241         if (keys == 2)
00242                 return key[1] == hs->in_phone_hash;
00243         else
00244                 return key[0] == hs->service;
00245 }
00246 
00251 void ns_remove(link_t *item)
00252 {
00253         assert(item);
00254         free(hash_table_get_instance(item, hashed_service_t, link));
00255 }
00256 

Generated on Sun Jun 18 18:00:18 2006 for HelenOS Userspace (ia64) by  doxygen 1.4.6