Changeset 58cbb0c8 in mainline
- Timestamp:
- 2011-09-01T22:19:21Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- aff587f
- Parents:
- 5f6e25e
- Location:
- uspace/srv/devman
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
r5f6e25e r58cbb0c8 30 30 * @{ 31 31 */ 32 /** @file Device Manager 33 * 34 * Locking order: 35 * (1) driver_t.driver_mutex 36 * (2) dev_tree_t.rwlock 37 * 38 * Synchronization: 39 * - device_tree.rwlock protects: 40 * - tree root, complete tree topology 41 * - complete contents of device and function nodes 42 * - dev_node_t.refcnt, fun_node_t.refcnt prevent nodes from 43 * being deallocated 44 * - find_xxx() functions increase reference count of returned object 45 * - find_xxx_no_lock() do not increase reference count 46 * 47 * TODO 48 * - Track all steady and transient device/function states 49 * - Check states, wait for steady state on certain operations 50 */ 32 51 33 52 #include <errno.h> … … 43 62 #include "devman.h" 44 63 45 fun_node_t *find_node_child(fun_node_t *parent, const char *name);64 static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *); 46 65 47 66 /* hash table operations */ … … 406 425 } 407 426 427 fun_add_ref(fun); 408 428 insert_fun_node(tree, fun, str_dup(""), NULL); 429 409 430 match_id_t *id = create_match_id(); 410 431 id->id = str_dup("root"); … … 422 443 } 423 444 445 dev_add_ref(dev); 424 446 insert_dev_node(tree, dev, fun); 425 447 … … 467 489 /** Assign a driver to a device. 468 490 * 491 * @param tree Device tree 469 492 * @param node The device's node in the device tree. 470 493 * @param drv The driver. 471 494 */ 472 void attach_driver(dev_ node_t *dev, driver_t *drv)495 void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv) 473 496 { 474 497 log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")", … … 476 499 477 500 fibril_mutex_lock(&drv->driver_mutex); 501 fibril_rwlock_write_lock(&tree->rwlock); 478 502 479 503 dev->drv = drv; 480 504 list_append(&dev->driver_devices, &drv->devices); 481 505 506 fibril_rwlock_write_unlock(&tree->rwlock); 482 507 fibril_mutex_unlock(&drv->driver_mutex); 483 508 } … … 485 510 /** Detach driver from device. 486 511 * 512 * @param tree Device tree 487 513 * @param node The device's node in the device tree. 488 514 * @param drv The driver. 489 515 */ 490 void detach_driver(dev_node_t *dev) 491 { 492 /* XXX need lock on dev */ 516 void detach_driver(dev_tree_t *tree, dev_node_t *dev) 517 { 493 518 driver_t *drv = dev->drv; 494 519 495 520 assert(drv != NULL); 521 496 522 log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")", 497 523 dev->pfun->pathname, drv->name); 498 524 499 525 fibril_mutex_lock(&drv->driver_mutex); 526 fibril_rwlock_write_lock(&tree->rwlock); 500 527 501 528 dev->drv = NULL; 502 529 list_remove(&dev->driver_devices); 503 530 531 fibril_rwlock_write_unlock(&tree->rwlock); 504 532 fibril_mutex_unlock(&drv->driver_mutex); 505 533 } … … 578 606 while (link != &driver->devices.head) { 579 607 dev = list_get_instance(link, dev_node_t, driver_devices); 608 fibril_rwlock_write_lock(&tree->rwlock); 609 580 610 if (dev->passed_to_driver) { 611 fibril_rwlock_write_unlock(&tree->rwlock); 581 612 link = link->next; 582 613 continue; 583 614 } 584 615 585 /* 586 * We remove the device from the list to allow safe adding 587 * of new devices (no one will touch our item this way). 588 */ 589 list_remove(link); 616 log_msg(LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n", 617 (int)atomic_get(&dev->refcnt)); 618 dev_add_ref(dev); 590 619 591 620 /* … … 594 623 */ 595 624 fibril_mutex_unlock(&driver->driver_mutex); 625 fibril_rwlock_write_unlock(&tree->rwlock); 596 626 597 627 add_device(driver, dev, tree); 628 629 dev_del_ref(dev); 598 630 599 631 /* … … 602 634 */ 603 635 fibril_mutex_lock(&driver->driver_mutex); 604 605 /*606 * Insert the device back.607 * The order is not relevant here so no harm is done608 * (actually, the order would be preserved in most cases).609 */610 list_append(link, &driver->devices);611 636 612 637 /* … … 701 726 char *loc_name = NULL; 702 727 728 assert(fibril_rwlock_is_locked(&tree->rwlock)); 729 703 730 asprintf(&loc_name, "%s", fun->pathname); 704 731 if (loc_name == NULL) … … 805 832 806 833 /* Attach the driver to the device. */ 807 attach_driver( dev, drv);834 attach_driver(tree, dev, drv); 808 835 809 836 fibril_mutex_lock(&drv->driver_mutex); … … 822 849 } 823 850 824 int driver_dev_remove(dev_ node_t *dev)851 int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev) 825 852 { 826 853 async_exch_t *exch; 827 854 sysarg_t retval; 828 855 driver_t *drv; 856 devman_handle_t handle; 829 857 830 858 assert(dev != NULL); 859 831 860 log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev); 861 862 fibril_rwlock_read_lock(&tree->rwlock); 832 863 drv = dev->drv; 864 handle = dev->handle; 865 fibril_rwlock_read_unlock(&tree->rwlock); 833 866 834 867 exch = async_exchange_begin(drv->sess); 835 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, dev->handle);868 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle); 836 869 async_exchange_end(exch); 837 870 … … 840 873 } 841 874 842 int driver_fun_online( fun_node_t *fun)875 int driver_fun_online(dev_tree_t *tree, fun_node_t *fun) 843 876 { 844 877 async_exch_t *exch; 845 878 sysarg_t retval; 846 879 driver_t *drv; 880 devman_handle_t handle; 847 881 848 882 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun); 883 884 fibril_rwlock_read_lock(&tree->rwlock); 885 849 886 if (fun->dev == NULL) { 850 887 /* XXX root function? */ 888 fibril_rwlock_read_unlock(&tree->rwlock); 851 889 return EINVAL; 852 890 } 853 891 854 892 drv = fun->dev->drv; 893 handle = fun->handle; 894 fibril_rwlock_read_unlock(&tree->rwlock); 855 895 856 896 exch = async_exchange_begin(drv->sess); 857 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, fun->handle);897 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle); 858 898 loc_exchange_end(exch); 859 899 … … 861 901 } 862 902 863 int driver_fun_offline( fun_node_t *fun)903 int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun) 864 904 { 865 905 async_exch_t *exch; 866 906 sysarg_t retval; 867 907 driver_t *drv; 908 devman_handle_t handle; 868 909 869 910 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun); 911 912 fibril_rwlock_read_lock(&tree->rwlock); 870 913 if (fun->dev == NULL) { 871 914 /* XXX root function? */ 915 fibril_rwlock_read_unlock(&tree->rwlock); 872 916 return EINVAL; 873 917 } 874 918 875 919 drv = fun->dev->drv; 920 handle = fun->handle; 921 fibril_rwlock_read_unlock(&tree->rwlock); 876 922 877 923 exch = async_exchange_begin(drv->sess); 878 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, fun->handle);924 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle); 879 925 loc_exchange_end(exch); 880 926 … … 909 955 if (!create_root_nodes(tree)) 910 956 return false; 911 957 912 958 /* Find suitable driver and start it. */ 913 return assign_driver(tree->root_node->child, drivers_list, tree); 959 dev_node_t *rdev = tree->root_node->child; 960 dev_add_ref(rdev); 961 int rc = assign_driver(rdev, drivers_list, tree); 962 dev_del_ref(rdev); 963 964 return rc; 914 965 } 915 966 … … 922 973 dev_node_t *create_dev_node(void) 923 974 { 924 dev_node_t *res = malloc(sizeof(dev_node_t)); 925 926 if (res != NULL) { 927 memset(res, 0, sizeof(dev_node_t)); 928 list_initialize(&res->functions); 929 link_initialize(&res->driver_devices); 930 link_initialize(&res->devman_dev); 931 } 932 933 return res; 975 dev_node_t *dev; 976 977 dev = calloc(1, sizeof(dev_node_t)); 978 if (dev == NULL) 979 return NULL; 980 981 atomic_set(&dev->refcnt, 0); 982 list_initialize(&dev->functions); 983 link_initialize(&dev->driver_devices); 984 link_initialize(&dev->devman_dev); 985 986 return dev; 934 987 } 935 988 … … 947 1000 } 948 1001 1002 /** Increase device node reference count. 1003 * 1004 * @param dev Device node 1005 */ 1006 void dev_add_ref(dev_node_t *dev) 1007 { 1008 atomic_inc(&dev->refcnt); 1009 } 1010 1011 /** Decrease device node reference count. 1012 * 1013 * When the count drops to zero the device node is freed. 1014 * 1015 * @param dev Device node 1016 */ 1017 void dev_del_ref(dev_node_t *dev) 1018 { 1019 if (atomic_predec(&dev->refcnt) == 0) 1020 delete_dev_node(dev); 1021 } 1022 1023 949 1024 /** Find the device node structure of the device witch has the specified handle. 950 1025 * … … 976 1051 fibril_rwlock_read_lock(&tree->rwlock); 977 1052 dev = find_dev_node_no_lock(tree, handle); 1053 if (dev != NULL) 1054 dev_add_ref(dev); 1055 978 1056 fibril_rwlock_read_unlock(&tree->rwlock); 979 1057 … … 1003 1081 list_get_instance(item, fun_node_t, dev_functions); 1004 1082 1005 if (pos < buf_cnt) 1083 if (pos < buf_cnt) { 1006 1084 hdl_buf[pos] = fun->handle; 1085 } 1086 1007 1087 pos++; 1008 1088 } … … 1020 1100 fun_node_t *create_fun_node(void) 1021 1101 { 1022 fun_node_t *res = malloc(sizeof(fun_node_t)); 1023 1024 if (res != NULL) { 1025 memset(res, 0, sizeof(fun_node_t)); 1026 link_initialize(&res->dev_functions); 1027 list_initialize(&res->match_ids.ids); 1028 link_initialize(&res->devman_fun); 1029 link_initialize(&res->loc_fun); 1030 } 1031 1032 return res; 1102 fun_node_t *fun; 1103 1104 fun = calloc(1, sizeof(fun_node_t)); 1105 if (fun == NULL) 1106 return NULL; 1107 1108 atomic_set(&fun->refcnt, 0); 1109 link_initialize(&fun->dev_functions); 1110 list_initialize(&fun->match_ids.ids); 1111 link_initialize(&fun->devman_fun); 1112 link_initialize(&fun->loc_fun); 1113 1114 return fun; 1033 1115 } 1034 1116 … … 1048 1130 } 1049 1131 1132 /** Increase function node reference count. 1133 * 1134 * @param fun Function node 1135 */ 1136 void fun_add_ref(fun_node_t *fun) 1137 { 1138 atomic_inc(&fun->refcnt); 1139 } 1140 1141 /** Decrease function node reference count. 1142 * 1143 * When the count drops to zero the function node is freed. 1144 * 1145 * @param fun Function node 1146 */ 1147 void fun_del_ref(fun_node_t *fun) 1148 { 1149 if (atomic_predec(&fun->refcnt) == 0) 1150 delete_fun_node(fun); 1151 } 1152 1050 1153 /** Find the function node with the specified handle. 1051 1154 * … … 1058 1161 unsigned long key = handle; 1059 1162 link_t *link; 1163 fun_node_t *fun; 1060 1164 1061 1165 assert(fibril_rwlock_is_locked(&tree->rwlock)); … … 1065 1169 return NULL; 1066 1170 1067 return hash_table_get_instance(link, fun_node_t, devman_fun); 1171 fun = hash_table_get_instance(link, fun_node_t, devman_fun); 1172 1173 return fun; 1068 1174 } 1069 1175 … … 1079 1185 1080 1186 fibril_rwlock_read_lock(&tree->rwlock); 1187 1081 1188 fun = find_fun_node_no_lock(tree, handle); 1189 if (fun != NULL) 1190 fun_add_ref(fun); 1191 1082 1192 fibril_rwlock_read_unlock(&tree->rwlock); 1083 1193 … … 1087 1197 /** Create and set device's full path in device tree. 1088 1198 * 1199 * @param tree Device tree 1089 1200 * @param node The device's device node. 1090 1201 * @param parent The parent device node. … … 1092 1203 * resources etc.). 1093 1204 */ 1094 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1095 { 1205 static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent) 1206 { 1207 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1096 1208 assert(fun->name != NULL); 1097 1209 … … 1120 1232 * 1121 1233 * @param tree The device tree. 1122 * @param node The newly added device node. 1123 * @param dev_name The name of the newly added device. 1124 * @param parent The parent device node. 1234 * @param dev The newly added device node. 1235 * @param pfun The parent function node. 1125 1236 * 1126 1237 * @return True on success, false otherwise (insufficient resources … … 1129 1240 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1130 1241 { 1131 assert(dev != NULL);1132 assert(tree != NULL);1133 1242 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1134 1243 … … 1155 1264 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev) 1156 1265 { 1157 assert(tree != NULL);1158 assert(dev != NULL);1159 1266 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1160 1267 … … 1174 1281 * 1175 1282 * @param tree The device tree. 1176 * @param nodeThe newly added function node.1177 * @param dev_name The name of the newly added function.1178 * @param parentOwning device node.1283 * @param fun The newly added function node. 1284 * @param fun_name The name of the newly added function. 1285 * @param dev Owning device node. 1179 1286 * 1180 1287 * @return True on success, false otherwise (insufficient resources … … 1186 1293 fun_node_t *pfun; 1187 1294 1188 assert(fun != NULL);1189 assert(tree != NULL);1190 1295 assert(fun_name != NULL); 1191 1296 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); … … 1198 1303 1199 1304 fun->name = fun_name; 1200 if (!set_fun_path( fun, pfun)) {1305 if (!set_fun_path(tree, fun, pfun)) { 1201 1306 return false; 1202 1307 } … … 1222 1327 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun) 1223 1328 { 1224 assert(tree != NULL);1225 assert(fun != NULL);1226 1329 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1227 1330 … … 1256 1359 1257 1360 fun_node_t *fun = tree->root_node; 1361 fun_add_ref(fun); 1258 1362 /* 1259 1363 * Relative path to the function from its parent (but with '/' at the … … 1273 1377 } 1274 1378 1275 fun = find_node_child(fun, rel_path + 1); 1379 fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1); 1380 fun_del_ref(fun); 1381 fun = cfun; 1276 1382 1277 1383 if (cont) { … … 1291 1397 * Device tree rwlock should be held at least for reading. 1292 1398 * 1399 * @param tree Device tree 1293 1400 * @param dev Device the function belongs to. 1294 1401 * @param name Function name (not path). … … 1296 1403 * @retval NULL No function with given name. 1297 1404 */ 1298 fun_node_t *find_fun_node_in_device(dev_ node_t *dev, const char *name)1299 { 1300 assert(dev != NULL); 1405 fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev, 1406 const char *name) 1407 { 1301 1408 assert(name != NULL); 1409 assert(fibril_rwlock_is_locked(&tree->rwlock)); 1302 1410 1303 1411 fun_node_t *fun; … … 1306 1414 fun = list_get_instance(link, fun_node_t, dev_functions); 1307 1415 1308 if (str_cmp(name, fun->name) == 0) 1416 if (str_cmp(name, fun->name) == 0) { 1417 fun_add_ref(fun); 1309 1418 return fun; 1419 } 1310 1420 } 1311 1421 … … 1317 1427 * Device tree rwlock should be held at least for reading. 1318 1428 * 1429 * @param tree Device tree 1319 1430 * @param parent The parent function node. 1320 1431 * @param name The name of the child function. 1321 1432 * @return The child function node. 1322 1433 */ 1323 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1324 { 1325 return find_fun_node_in_device(pfun->child, name); 1434 static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun, 1435 const char *name) 1436 { 1437 return find_fun_node_in_device(tree, pfun->child, name); 1326 1438 } 1327 1439 … … 1336 1448 fibril_rwlock_read_lock(&tree->rwlock); 1337 1449 link = hash_table_find(&tree->loc_functions, &key); 1338 if (link != NULL) 1450 if (link != NULL) { 1339 1451 fun = hash_table_get_instance(link, fun_node_t, loc_fun); 1452 fun_add_ref(fun); 1453 } 1340 1454 fibril_rwlock_read_unlock(&tree->rwlock); 1341 1455 … … 1345 1459 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1346 1460 { 1461 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1462 1347 1463 unsigned long key = (unsigned long) fun->service_id; 1348 fibril_rwlock_write_lock(&tree->rwlock);1349 1464 hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun); 1350 fibril_rwlock_write_unlock(&tree->rwlock);1351 1465 } 1352 1466 -
uspace/srv/devman/devman.h
r5f6e25e r58cbb0c8 128 128 /** Device node in the device tree. */ 129 129 struct dev_node { 130 /** Reference count */ 131 atomic_t refcnt; 132 130 133 /** The global unique identifier of the device. */ 131 134 devman_handle_t handle; … … 156 159 /** Function node in the device tree. */ 157 160 struct fun_node { 161 /** Reference count */ 162 atomic_t refcnt; 163 158 164 /** The global unique identifier of the function */ 159 165 devman_handle_t handle; … … 239 245 240 246 extern void add_driver(driver_list_t *, driver_t *); 241 extern void attach_driver(dev_ node_t *, driver_t *);242 extern void detach_driver(dev_ node_t *);247 extern void attach_driver(dev_tree_t *, dev_node_t *, driver_t *); 248 extern void detach_driver(dev_tree_t *, dev_node_t *); 243 249 extern void add_device(driver_t *, dev_node_t *, dev_tree_t *); 244 250 extern bool start_driver(driver_t *); 245 extern int driver_dev_remove(dev_ node_t *);246 extern int driver_fun_online( fun_node_t *);247 extern int driver_fun_offline( fun_node_t *);251 extern int driver_dev_remove(dev_tree_t *, dev_node_t *); 252 extern int driver_fun_online(dev_tree_t *, fun_node_t *); 253 extern int driver_fun_offline(dev_tree_t *, fun_node_t *); 248 254 249 255 extern driver_t *find_driver(driver_list_t *, const char *); … … 258 264 extern dev_node_t *create_dev_node(void); 259 265 extern void delete_dev_node(dev_node_t *node); 266 extern void dev_add_ref(dev_node_t *); 267 extern void dev_del_ref(dev_node_t *); 260 268 extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, 261 269 devman_handle_t handle); … … 267 275 extern fun_node_t *create_fun_node(void); 268 276 extern void delete_fun_node(fun_node_t *); 277 extern void fun_add_ref(fun_node_t *); 278 extern void fun_del_ref(fun_node_t *); 269 279 extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, 270 280 devman_handle_t handle); 271 281 extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle); 272 282 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *); 273 extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *); 283 extern fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *, 284 const char *); 274 285 275 286 /* Device tree */ -
uspace/srv/devman/main.c
r5f6e25e r58cbb0c8 242 242 243 243 fibril_rwlock_write_lock(&device_tree.rwlock); 244 244 245 245 if (fun->ftype == fun_inner) { 246 246 dev = create_dev_node(); 247 247 if (dev == NULL) { 248 248 fibril_rwlock_write_unlock(&device_tree.rwlock); 249 delete_fun_node(fun);250 249 return ENOMEM; 251 250 } 252 251 253 252 insert_dev_node(&device_tree, dev, fun); 254 } 255 256 fibril_rwlock_write_unlock(&device_tree.rwlock); 253 dev_add_ref(dev); 254 } 257 255 258 256 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); … … 283 281 } 284 282 283 fibril_rwlock_write_unlock(&device_tree.rwlock); 284 285 285 return EOK; 286 286 } … … 289 289 { 290 290 int rc; 291 292 fibril_rwlock_write_lock(&device_tree.rwlock); 291 293 292 294 if (fun->ftype == fun_inner) { … … 296 298 dev_node_t *dev = fun->child; 297 299 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); 299 304 if (rc != EOK) { 305 dev_del_ref(dev); 300 306 return ENOTSUP; 301 307 } 302 detach_driver(dev); 308 309 detach_driver(&device_tree, dev); 310 303 311 fibril_rwlock_write_lock(&device_tree.rwlock); 304 312 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); 307 318 } 308 319 } else { … … 310 321 rc = loc_service_unregister(fun->service_id); 311 322 if (rc != EOK) { 323 fibril_rwlock_write_unlock(&device_tree.rwlock); 312 324 log_msg(LVL_ERROR, "Failed unregistering tree service."); 313 325 return EIO; … … 317 329 } 318 330 331 fibril_rwlock_write_unlock(&device_tree.rwlock); 332 319 333 return EOK; 320 334 } … … 331 345 dev_tree_t *tree = &device_tree; 332 346 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); 337 348 if (pdev == NULL) { 338 fibril_rwlock_write_unlock(&tree->rwlock);339 349 async_answer_0(callid, ENOENT); 340 350 return; … … 347 357 (int) ftype); 348 358 349 fibril_rwlock_write_unlock(&tree->rwlock);359 dev_del_ref(pdev); 350 360 async_answer_0(callid, EINVAL); 351 361 return; … … 355 365 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 356 366 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) { 357 376 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); 365 378 async_answer_0(callid, EEXISTS); 366 379 printf(NAME ": Warning, driver tried to register `%s' twice.\n", … … 371 384 372 385 fun_node_t *fun = create_fun_node(); 386 fun_add_ref(fun); 373 387 fun->ftype = ftype; 374 388 375 389 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 376 390 fibril_rwlock_write_unlock(&tree->rwlock); 391 dev_del_ref(pdev); 377 392 delete_fun_node(fun); 378 393 async_answer_0(callid, ENOMEM); … … 381 396 382 397 fibril_rwlock_write_unlock(&tree->rwlock); 398 dev_del_ref(pdev); 383 399 384 400 devman_receive_match_ids(match_count, &fun->match_ids); … … 408 424 async_answer_0(callid, rc); 409 425 return; 410 } 426 } 411 427 412 428 fun_node_t *fun = find_fun_node(&device_tree, handle); … … 415 431 return; 416 432 } 433 434 fibril_rwlock_read_lock(&device_tree.rwlock); 417 435 418 436 rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING); … … 427 445 fun->pathname, cat_name); 428 446 447 fibril_rwlock_read_unlock(&device_tree.rwlock); 448 fun_del_ref(fun); 449 429 450 async_answer_0(callid, EOK); 430 451 } … … 440 461 441 462 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); 450 477 451 478 rc = online_function(fun); 452 479 if (rc != EOK) { 453 480 printf("devman_drv_fun_online() online_fun->ERROR\n"); 481 fun_del_ref(fun); 454 482 async_answer_0(iid, (sysarg_t) rc); 455 483 return; 456 484 } 485 486 fun_del_ref(fun); 457 487 printf("devman_drv_fun_online() online_fun->OK\n"); 458 488 … … 470 500 int rc; 471 501 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 472 508 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); 480 515 481 516 rc = offline_function(fun); 482 517 if (rc != EOK) { 518 fun_del_ref(fun); 483 519 async_answer_0(iid, (sysarg_t) rc); 484 520 return; 485 521 } 486 522 523 fun_del_ref(fun); 487 524 async_answer_0(iid, (sysarg_t) EOK); 488 525 } … … 495 532 int rc; 496 533 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 497 541 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 }505 542 506 543 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname); … … 508 545 if (fun->ftype == fun_inner) { 509 546 /* Handle possible descendants */ 510 /* TODO */547 /* TODO - This is a surprise removal */ 511 548 if (fun->child != NULL) { 512 549 log_msg(LVL_WARN, "devman_remove_function(): not handling " … … 521 558 "service."); 522 559 fibril_rwlock_write_unlock(&tree->rwlock); 560 fun_del_ref(fun); 523 561 async_answer_0(callid, EIO); 524 562 return; … … 529 567 remove_fun_node(&device_tree, fun); 530 568 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); 532 574 533 575 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); … … 621 663 { 622 664 char *pathname; 665 devman_handle_t handle; 623 666 624 667 int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0); … … 637 680 } 638 681 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); 640 690 } 641 691 … … 655 705 if (!async_data_read_receive(&data_callid, &data_len)) { 656 706 async_answer_0(iid, EINVAL); 707 fun_del_ref(fun); 657 708 return; 658 709 } … … 662 713 async_answer_0(data_callid, ENOMEM); 663 714 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); 666 720 667 721 size_t sent_length = str_size(fun->name); … … 673 727 async_answer_0(iid, EOK); 674 728 729 fibril_rwlock_read_unlock(&device_tree.rwlock); 730 fun_del_ref(fun); 675 731 free(buffer); 676 732 } … … 692 748 if (!async_data_read_receive(&data_callid, &data_len)) { 693 749 async_answer_0(iid, EINVAL); 750 fun_del_ref(fun); 694 751 return; 695 752 } … … 699 756 async_answer_0(data_callid, ENOMEM); 700 757 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 704 764 size_t sent_length = str_size(fun->pathname); 705 765 if (sent_length > data_len) { … … 710 770 async_answer_0(iid, EOK); 711 771 772 fibril_rwlock_read_unlock(&device_tree.rwlock); 773 fun_del_ref(fun); 712 774 free(buffer); 713 775 } … … 777 839 778 840 if (fun->child == NULL) { 841 fun_del_ref(fun); 779 842 fibril_rwlock_read_unlock(&device_tree.rwlock); 780 843 async_answer_0(iid, ENOENT); … … 784 847 async_answer_1(iid, EOK, fun->child->handle); 785 848 849 fun_del_ref(fun); 786 850 fibril_rwlock_read_unlock(&device_tree.rwlock); 787 851 } … … 798 862 int rc; 799 863 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)); 804 865 if (fun == NULL) { 805 866 async_answer_0(iid, ENOENT); … … 807 868 } 808 869 809 rc = driver_fun_online(fun); 870 rc = driver_fun_online(&device_tree, fun); 871 fun_del_ref(fun); 810 872 811 873 async_answer_0(iid, (sysarg_t) rc); … … 825 887 int rc; 826 888 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)); 831 890 if (fun == NULL) { 832 891 async_answer_0(iid, ENOENT); … … 834 893 } 835 894 836 rc = driver_fun_offline(fun); 895 rc = driver_fun_offline(&device_tree, fun); 896 fun_del_ref(fun); 837 897 838 898 async_answer_0(iid, (sysarg_t) rc); … … 851 911 } 852 912 913 fibril_rwlock_read_lock(&device_tree.rwlock); 853 914 async_answer_1(iid, EOK, fun->handle); 915 fibril_rwlock_read_unlock(&device_tree.rwlock); 916 fun_del_ref(fun); 854 917 } 855 918 … … 909 972 if (fun == NULL) 910 973 dev = find_dev_node(&device_tree, handle); 911 else 974 else { 975 fibril_rwlock_read_lock(&device_tree.rwlock); 912 976 dev = fun->dev; 977 if (dev != NULL) 978 dev_add_ref(dev); 979 fibril_rwlock_read_unlock(&device_tree.rwlock); 980 } 913 981 914 982 /* … … 922 990 "function with handle %" PRIun " was found.", handle); 923 991 async_answer_0(iid, ENOENT); 924 return;992 goto cleanup; 925 993 } 926 994 … … 930 998 handle); 931 999 async_answer_0(iid, ENOENT); 932 return;1000 goto cleanup; 933 1001 } 934 1002 … … 952 1020 "the device %" PRIun " is not in usable state.", handle); 953 1021 async_answer_0(iid, ENOENT); 954 return;1022 goto cleanup; 955 1023 } 956 1024 … … 965 1033 "Could not forward to driver `%s'.", driver->name); 966 1034 async_answer_0(iid, EINVAL); 967 return;1035 goto cleanup; 968 1036 } 969 1037 … … 981 1049 async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE); 982 1050 async_exchange_end(exch); 1051 1052 cleanup: 1053 if (dev != NULL) 1054 dev_del_ref(dev); 1055 if (fun != NULL) 1056 fun_del_ref(fun); 983 1057 } 984 1058 … … 1000 1074 } 1001 1075 1076 fibril_rwlock_read_lock(&device_tree.rwlock); 1002 1077 dev = fun->dev; 1078 fun_del_ref(fun); 1003 1079 1004 1080 async_exch_t *exch = async_exchange_begin(dev->drv->sess); … … 1006 1082 IPC_FF_NONE); 1007 1083 async_exchange_end(exch); 1084 1085 fibril_rwlock_read_unlock(&device_tree.rwlock); 1008 1086 1009 1087 log_msg(LVL_DEBUG,
Note:
See TracChangeset
for help on using the changeset viewer.