Changeset 58cbb0c8 in mainline for uspace/srv/devman/main.c


Ignore:
Timestamp:
2011-09-01T22:19:21Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
aff587f
Parents:
5f6e25e
Message:

Reference counting of device and function nodes in devman.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/main.c

    r5f6e25e r58cbb0c8  
    242242       
    243243        fibril_rwlock_write_lock(&device_tree.rwlock);
    244        
     244
    245245        if (fun->ftype == fun_inner) {
    246246                dev = create_dev_node();
    247247                if (dev == NULL) {
    248248                        fibril_rwlock_write_unlock(&device_tree.rwlock);
    249                         delete_fun_node(fun);
    250249                        return ENOMEM;
    251250                }
    252251
    253252                insert_dev_node(&device_tree, dev, fun);
    254         }
    255        
    256         fibril_rwlock_write_unlock(&device_tree.rwlock);
     253                dev_add_ref(dev);
     254        }
    257255       
    258256        log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
     
    283281        }
    284282       
     283        fibril_rwlock_write_unlock(&device_tree.rwlock);
     284       
    285285        return EOK;
    286286}
     
    289289{
    290290        int rc;
     291       
     292        fibril_rwlock_write_lock(&device_tree.rwlock);
    291293       
    292294        if (fun->ftype == fun_inner) {
     
    296298                        dev_node_t *dev = fun->child;
    297299                       
    298                         rc = driver_dev_remove(dev);
     300                        dev_add_ref(dev);
     301                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     302                       
     303                        rc = driver_dev_remove(&device_tree, dev);
    299304                        if (rc != EOK) {
     305                                dev_del_ref(dev);
    300306                                return ENOTSUP;
    301307                        }
    302                         detach_driver(dev);
     308                       
     309                        detach_driver(&device_tree, dev);
     310                       
    303311                        fibril_rwlock_write_lock(&device_tree.rwlock);
    304312                        remove_dev_node(&device_tree, dev);
    305                         fibril_rwlock_write_unlock(&device_tree.rwlock);
    306                         delete_dev_node(dev);
     313                       
     314                        /* Delete ref created when node was inserted */
     315                        dev_del_ref(dev);
     316                        /* Delete ref created by dev_add_ref(dev) above */
     317                        dev_del_ref(dev);
    307318                }
    308319        } else {
     
    310321                rc = loc_service_unregister(fun->service_id);
    311322                if (rc != EOK) {
     323                        fibril_rwlock_write_unlock(&device_tree.rwlock);
    312324                        log_msg(LVL_ERROR, "Failed unregistering tree service.");
    313325                        return EIO;
     
    317329        }
    318330       
     331        fibril_rwlock_write_unlock(&device_tree.rwlock);
     332       
    319333        return EOK;
    320334}
     
    331345        dev_tree_t *tree = &device_tree;
    332346       
    333         fibril_rwlock_write_lock(&tree->rwlock);
    334 
    335         dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle);
    336        
     347        dev_node_t *pdev = find_dev_node(&device_tree, dev_handle);
    337348        if (pdev == NULL) {
    338                 fibril_rwlock_write_unlock(&tree->rwlock);
    339349                async_answer_0(callid, ENOENT);
    340350                return;
     
    347357                    (int) ftype);
    348358
    349                 fibril_rwlock_write_unlock(&tree->rwlock);
     359                dev_del_ref(pdev);
    350360                async_answer_0(callid, EINVAL);
    351361                return;
     
    355365        int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
    356366        if (rc != EOK) {
     367                dev_del_ref(pdev);
     368                async_answer_0(callid, rc);
     369                return;
     370        }
     371       
     372        fibril_rwlock_write_lock(&tree->rwlock);
     373       
     374        /* Check that function with same name is not there already. */
     375        if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) {
    357376                fibril_rwlock_write_unlock(&tree->rwlock);
    358                 async_answer_0(callid, rc);
    359                 return;
    360         }
    361        
    362         /* Check that function with same name is not there already. */
    363         if (find_fun_node_in_device(pdev, fun_name) != NULL) {
    364                 fibril_rwlock_write_unlock(&tree->rwlock);
     377                dev_del_ref(pdev);
    365378                async_answer_0(callid, EEXISTS);
    366379                printf(NAME ": Warning, driver tried to register `%s' twice.\n",
     
    371384       
    372385        fun_node_t *fun = create_fun_node();
     386        fun_add_ref(fun);
    373387        fun->ftype = ftype;
    374388       
    375389        if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
    376390                fibril_rwlock_write_unlock(&tree->rwlock);
     391                dev_del_ref(pdev);
    377392                delete_fun_node(fun);
    378393                async_answer_0(callid, ENOMEM);
     
    381396       
    382397        fibril_rwlock_write_unlock(&tree->rwlock);
     398        dev_del_ref(pdev);
    383399       
    384400        devman_receive_match_ids(match_count, &fun->match_ids);
     
    408424                async_answer_0(callid, rc);
    409425                return;
    410         }       
     426        }
    411427       
    412428        fun_node_t *fun = find_fun_node(&device_tree, handle);
     
    415431                return;
    416432        }
     433       
     434        fibril_rwlock_read_lock(&device_tree.rwlock);
    417435       
    418436        rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING);
     
    427445            fun->pathname, cat_name);
    428446
     447        fibril_rwlock_read_unlock(&device_tree.rwlock);
     448        fun_del_ref(fun);
     449
    429450        async_answer_0(callid, EOK);
    430451}
     
    440461
    441462        printf("devman_drv_fun_online()\n");
    442         fibril_rwlock_write_lock(&device_tree.rwlock);
    443         fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
    444         fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */
    445        
    446         if (fun == NULL || fun->dev == NULL || fun->dev->drv != drv) {
    447                 async_answer_0(iid, ENOENT);
    448                 return;
    449         }
     463        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     464        if (fun == NULL) {
     465                async_answer_0(iid, ENOENT);
     466                return;
     467        }
     468       
     469        fibril_rwlock_read_lock(&device_tree.rwlock);
     470        if (fun->dev == NULL || fun->dev->drv != drv) {
     471                fibril_rwlock_read_unlock(&device_tree.rwlock);
     472                fun_del_ref(fun);
     473                async_answer_0(iid, ENOENT);
     474                return;
     475        }
     476        fibril_rwlock_read_unlock(&device_tree.rwlock);
    450477       
    451478        rc = online_function(fun);
    452479        if (rc != EOK) {
    453480                printf("devman_drv_fun_online() online_fun->ERROR\n");
     481                fun_del_ref(fun);
    454482                async_answer_0(iid, (sysarg_t) rc);
    455483                return;
    456484        }
     485       
     486        fun_del_ref(fun);
    457487        printf("devman_drv_fun_online() online_fun->OK\n");
    458488       
     
    470500        int rc;
    471501
     502        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     503        if (fun == NULL) {
     504                async_answer_0(iid, ENOENT);
     505                return;
     506        }
     507       
    472508        fibril_rwlock_write_lock(&device_tree.rwlock);
    473         fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
    474         fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */
    475        
    476         if (fun == NULL || fun->dev == NULL || fun->dev->drv != drv) {
    477                 async_answer_0(iid, ENOENT);
    478                 return;
    479         }
     509        if (fun->dev == NULL || fun->dev->drv != drv) {
     510                fun_del_ref(fun);
     511                async_answer_0(iid, ENOENT);
     512                return;
     513        }
     514        fibril_rwlock_write_unlock(&device_tree.rwlock);
    480515       
    481516        rc = offline_function(fun);
    482517        if (rc != EOK) {
     518                fun_del_ref(fun);
    483519                async_answer_0(iid, (sysarg_t) rc);
    484520                return;
    485521        }
    486522       
     523        fun_del_ref(fun);
    487524        async_answer_0(iid, (sysarg_t) EOK);
    488525}
     
    495532        int rc;
    496533       
     534       
     535        fun_node_t *fun = find_fun_node(&device_tree, fun_handle);
     536        if (fun == NULL) {
     537                async_answer_0(callid, ENOENT);
     538                return;
     539        }
     540       
    497541        fibril_rwlock_write_lock(&tree->rwlock);
    498        
    499         fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle);
    500         if (fun == NULL) {
    501                 fibril_rwlock_write_unlock(&tree->rwlock);
    502                 async_answer_0(callid, ENOENT);
    503                 return;
    504         }
    505542       
    506543        log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
     
    508545        if (fun->ftype == fun_inner) {
    509546                /* Handle possible descendants */
    510                 /* TODO */
     547                /* TODO - This is a surprise removal */
    511548                if (fun->child != NULL) {
    512549                        log_msg(LVL_WARN, "devman_remove_function(): not handling "
     
    521558                                    "service.");
    522559                                fibril_rwlock_write_unlock(&tree->rwlock);
     560                                fun_del_ref(fun);
    523561                                async_answer_0(callid, EIO);
    524562                                return;
     
    529567        remove_fun_node(&device_tree, fun);
    530568        fibril_rwlock_write_unlock(&tree->rwlock);
    531         delete_fun_node(fun);
     569       
     570        /* Delete ref added when inserting function into tree */
     571        fun_del_ref(fun);
     572        /* Delete ref added above when looking up function */
     573        fun_del_ref(fun);
    532574       
    533575        log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
     
    621663{
    622664        char *pathname;
     665        devman_handle_t handle;
    623666       
    624667        int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
     
    637680        }
    638681
    639         async_answer_1(iid, EOK, fun->handle);
     682        fibril_rwlock_read_lock(&device_tree.rwlock);
     683        handle = fun->handle;
     684        fibril_rwlock_read_unlock(&device_tree.rwlock);
     685
     686        /* Delete reference created above by find_fun_node_by_path() */
     687        fun_del_ref(fun);
     688
     689        async_answer_1(iid, EOK, handle);
    640690}
    641691
     
    655705        if (!async_data_read_receive(&data_callid, &data_len)) {
    656706                async_answer_0(iid, EINVAL);
     707                fun_del_ref(fun);
    657708                return;
    658709        }
     
    662713                async_answer_0(data_callid, ENOMEM);
    663714                async_answer_0(iid, ENOMEM);
    664                 return;
    665         }
     715                fun_del_ref(fun);
     716                return;
     717        }
     718
     719        fibril_rwlock_read_lock(&device_tree.rwlock);
    666720
    667721        size_t sent_length = str_size(fun->name);
     
    673727        async_answer_0(iid, EOK);
    674728
     729        fibril_rwlock_read_unlock(&device_tree.rwlock);
     730        fun_del_ref(fun);
    675731        free(buffer);
    676732}
     
    692748        if (!async_data_read_receive(&data_callid, &data_len)) {
    693749                async_answer_0(iid, EINVAL);
     750                fun_del_ref(fun);
    694751                return;
    695752        }
     
    699756                async_answer_0(data_callid, ENOMEM);
    700757                async_answer_0(iid, ENOMEM);
    701                 return;
    702         }
    703 
     758                fun_del_ref(fun);
     759                return;
     760        }
     761       
     762        fibril_rwlock_read_lock(&device_tree.rwlock);
     763       
    704764        size_t sent_length = str_size(fun->pathname);
    705765        if (sent_length > data_len) {
     
    710770        async_answer_0(iid, EOK);
    711771
     772        fibril_rwlock_read_unlock(&device_tree.rwlock);
     773        fun_del_ref(fun);
    712774        free(buffer);
    713775}
     
    777839       
    778840        if (fun->child == NULL) {
     841                fun_del_ref(fun);
    779842                fibril_rwlock_read_unlock(&device_tree.rwlock);
    780843                async_answer_0(iid, ENOENT);
     
    784847        async_answer_1(iid, EOK, fun->child->handle);
    785848       
     849        fun_del_ref(fun);
    786850        fibril_rwlock_read_unlock(&device_tree.rwlock);
    787851}
     
    798862        int rc;
    799863
    800         fibril_rwlock_write_lock(&device_tree.rwlock);
    801         fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
    802         fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */
    803        
     864        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    804865        if (fun == NULL) {
    805866                async_answer_0(iid, ENOENT);
     
    807868        }
    808869       
    809         rc = driver_fun_online(fun);
     870        rc = driver_fun_online(&device_tree, fun);
     871        fun_del_ref(fun);
    810872       
    811873        async_answer_0(iid, (sysarg_t) rc);
     
    825887        int rc;
    826888
    827         fibril_rwlock_write_lock(&device_tree.rwlock);
    828         fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
    829         fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */
    830        
     889        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    831890        if (fun == NULL) {
    832891                async_answer_0(iid, ENOENT);
     
    834893        }
    835894       
    836         rc = driver_fun_offline(fun);
     895        rc = driver_fun_offline(&device_tree, fun);
     896        fun_del_ref(fun);
    837897       
    838898        async_answer_0(iid, (sysarg_t) rc);
     
    851911        }
    852912
     913        fibril_rwlock_read_lock(&device_tree.rwlock);
    853914        async_answer_1(iid, EOK, fun->handle);
     915        fibril_rwlock_read_unlock(&device_tree.rwlock);
     916        fun_del_ref(fun);
    854917}
    855918
     
    909972        if (fun == NULL)
    910973                dev = find_dev_node(&device_tree, handle);
    911         else
     974        else {
     975                fibril_rwlock_read_lock(&device_tree.rwlock);
    912976                dev = fun->dev;
     977                if (dev != NULL)
     978                        dev_add_ref(dev);
     979                fibril_rwlock_read_unlock(&device_tree.rwlock);
     980        }
    913981
    914982        /*
     
    922990                    "function with handle %" PRIun " was found.", handle);
    923991                async_answer_0(iid, ENOENT);
    924                 return;
     992                goto cleanup;
    925993        }
    926994
     
    930998                    handle);
    931999                async_answer_0(iid, ENOENT);
    932                 return;
     1000                goto cleanup;
    9331001        }
    9341002       
     
    9521020                    "the device %" PRIun " is not in usable state.", handle);
    9531021                async_answer_0(iid, ENOENT);
    954                 return;
     1022                goto cleanup;
    9551023        }
    9561024       
     
    9651033                    "Could not forward to driver `%s'.", driver->name);
    9661034                async_answer_0(iid, EINVAL);
    967                 return;
     1035                goto cleanup;
    9681036        }
    9691037
     
    9811049        async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE);
    9821050        async_exchange_end(exch);
     1051
     1052cleanup:
     1053        if (dev != NULL)
     1054                dev_del_ref(dev);
     1055        if (fun != NULL)
     1056                fun_del_ref(fun);
    9831057}
    9841058
     
    10001074        }
    10011075       
     1076        fibril_rwlock_read_lock(&device_tree.rwlock);
    10021077        dev = fun->dev;
     1078        fun_del_ref(fun);
    10031079       
    10041080        async_exch_t *exch = async_exchange_begin(dev->drv->sess);
     
    10061082            IPC_FF_NONE);
    10071083        async_exchange_end(exch);
     1084       
     1085        fibril_rwlock_read_unlock(&device_tree.rwlock);
    10081086       
    10091087        log_msg(LVL_DEBUG,
Note: See TracChangeset for help on using the changeset viewer.