Changeset 1fcfc94 in mainline


Ignore:
Timestamp:
2009-03-02T17:35:03Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6519d6f
Parents:
a32c9bb
Message:

add support for pending (blocking) connections to services
cleanup & cstyle

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/ns/ns.c

    ra32c9bb r1fcfc94  
    2929/** @addtogroup ns
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
    34  * @file        ns.c
    35  * @brief       Naming service for HelenOS IPC.
     34 * @file  ns.c
     35 * @brief Naming service for HelenOS IPC.
    3636 */
    3737
     
    5353#include <as.h>
    5454
    55 #define NAME    "ns"
    56 
    57 #define NS_HASH_TABLE_CHAINS    20
     55#define NAME  "ns"
     56
     57#define NS_HASH_TABLE_CHAINS  20
    5858
    5959static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
    60 static int connect_to_service(ipcarg_t service, ipc_call_t *call,
     60static void connect_to_service(ipcarg_t service, ipc_call_t *call,
    6161    ipc_callid_t callid);
    6262
     
    6565void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
    6666    ipc_callid_t callid);
     67
    6768
    6869/* Static functions implementing NS hash table operations. */
     
    8485typedef struct {
    8586        link_t link;
    86         ipcarg_t service;               /**< Number of the service. */
    87         ipcarg_t phone;                 /**< Phone registered with the service. */
    88         ipcarg_t in_phone_hash;         /**< Incoming 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. */
    8990} hashed_service_t;
    9091
    91 static void *clockaddr = NULL;
    92 static void *klogaddr = NULL;
     92/** Pending connection structure. */
     93typedef 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
     101static link_t pending_req;
    93102
    94103/** Request for connection to a clonable service. */
     
    103112static link_t cs_req;
    104113
     114static void *clockaddr = NULL;
     115static void *klogaddr = NULL;
     116
    105117/** Return true if @a service is clonable. */
    106118static bool service_clonable(int service)
    107119{
    108         return service == SERVICE_LOAD;
     120        return (service == SERVICE_LOAD);
    109121}
    110122
     
    129141}
    130142
     143/** Process pending connection requests */
     144static void process_pending_req()
     145{
     146        link_t *cur;
     147       
     148loop:
     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
    131175int main(int argc, char **argv)
    132176{
    133177        printf(NAME ": HelenOS IPC Naming Service\n");
    134178       
    135         ipc_call_t call;
    136         ipc_callid_t callid;
    137        
    138         ipcarg_t retval;
    139 
    140179        if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3,
    141180            &ns_hash_table_ops)) {
    142                 printf(NAME ": No memory available\n");
     181                printf(NAME ": No memory available for services\n");
    143182                return ENOMEM;
    144183        }
    145 
     184       
     185        list_initialize(&pending_req);
    146186        list_initialize(&cs_req);
    147187       
    148188        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               
    151196                switch (IPC_GET_METHOD(call)) {
    152197                case IPC_M_SHARE_IN:
     
    187232                                continue;
    188233                        } 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;
    191237                        }
    192238                        break;
     
    195241                        break;
    196242                }
    197                 if (!(callid & IPC_CALLID_NOTIFICATION)) {
     243               
     244                if (!(callid & IPC_CALLID_NOTIFICATION))
    198245                        ipc_answer_0(callid, retval);
    199                 }
    200246        }
    201247       
     
    206252/** Register service.
    207253 *
    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 *
    213260 */
    214261int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
     
    219266                0
    220267        };
    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))
    224270                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)
    229274                return ENOMEM;
    230         }
    231                        
     275       
    232276        link_initialize(&hs->link);
    233277        hs->service = service;
     
    235279        hs->in_phone_hash = call->in_phone_hash;
    236280        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 */
     294void 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                        }
    237312                       
    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       
     328out:
     329        if (!(callid & IPC_CALLID_NOTIFICATION))
     330                ipc_answer_0(callid, retval);
    262331}
    263332
    264333/** Register clonable service.
    265334 *
    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 *
    269339 */
    270340void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
    271341    ipc_callid_t callid)
    272342{
    273         int rc;
    274         cs_req_t *csr;
    275 
    276343        if (list_empty(&cs_req)) {
    277344                /* There was no pending connection request. */
     
    280347                return;
    281348        }
    282 
    283         csr = 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);
    284351        list_remove(&csr->link);
    285 
     352       
    286353        /* Currently we can only handle a single type of clonable service. */
    287354        assert(csr->service == SERVICE_LOAD);
    288 
     355       
    289356        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),
    292359                IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
    293 
     360       
    294361        free(csr);
    295362}
     
    297364/** Connect client to clonable service.
    298365 *
    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 *
    304372 */
    305373void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
    306374    ipc_callid_t callid)
    307375{
    308         int rc;
    309         cs_req_t *csr;
    310 
    311376        assert(service == SERVICE_LOAD);
    312 
    313         csr = malloc(sizeof(cs_req_t));
     377       
     378        cs_req_t *csr = malloc(sizeof(cs_req_t));
    314379        if (csr == NULL) {
    315380                ipc_answer_0(callid, ENOMEM);
    316381                return;
    317382        }
    318 
     383       
    319384        /* Spawn a loader. */
    320         rc = loader_spawn("loader");
    321 
     385        int rc = loader_spawn("loader");
     386       
    322387        if (rc < 0) {
    323388                free(csr);
     
    325390                return;
    326391        }
    327 
     392       
    328393        csr->service = service;
    329394        csr->call = *call;
    330395        csr->callid = callid;
    331 
     396       
    332397        /*
    333398         * We can forward the call only after the server we spawned connects
     
    341406 *
    342407 * @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 *
    344410 * @return Hash index corresponding to key[0].
     411 *
    345412 */
    346413hash_index_t ns_hash(unsigned long *key)
    347414{
    348415        assert(key);
    349         return *key % NS_HASH_TABLE_CHAINS;
     416        return (*key % NS_HASH_TABLE_CHAINS);
    350417}
    351418
     
    358425 * as a nasty hack.
    359426 *
    360  * @param key Array of keys.
     427 * @param key  Array of keys.
    361428 * @param keys Must be lesser or equal to 3.
    362429 * @param item Pointer to a hash table item.
     430 *
    363431 * @return Non-zero if the key matches the item, zero otherwise.
     432 *
    364433 */
    365434int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
    366435{
    367         hashed_service_t *hs;
    368 
    369436        assert(key);
    370437        assert(keys <= 3);
    371438        assert(item);
    372439       
    373         hs = hash_table_get_instance(item, hashed_service_t, link);
     440        hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
    374441       
    375442        if (keys == 2)
     
    382449 *
    383450 * @param item Item that was removed from the hash table.
     451 *
    384452 */
    385453void ns_remove(link_t *item)
     
    389457}
    390458
    391 /** 
     459/**
    392460 * @}
    393461 */
Note: See TracChangeset for help on using the changeset viewer.