Changes in uspace/srv/devman/devman.c [c1a0488:45059d6b] in mainline
- File:
-
- 1 edited
-
uspace/srv/devman/devman.c (modified) (40 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
rc1a0488 r45059d6b 30 30 * @{ 31 31 */ 32 /** @file Device Manager33 *34 * Locking order:35 * (1) driver_t.driver_mutex36 * (2) dev_tree_t.rwlock37 *38 * Synchronization:39 * - device_tree.rwlock protects:40 * - tree root, complete tree topology41 * - complete contents of device and function nodes42 * - dev_node_t.refcnt, fun_node_t.refcnt prevent nodes from43 * being deallocated44 * - find_xxx() functions increase reference count of returned object45 * - find_xxx_no_lock() do not increase reference count46 *47 * TODO48 * - Track all steady and transient device/function states49 * - Check states, wait for steady state on certain operations50 */51 32 52 33 #include <errno.h> … … 62 43 #include "devman.h" 63 44 64 static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);45 fun_node_t *find_node_child(fun_node_t *parent, const char *name); 65 46 66 47 /* hash table operations */ … … 425 406 } 426 407 427 fun_add_ref(fun);428 408 insert_fun_node(tree, fun, str_dup(""), NULL); 429 430 409 match_id_t *id = create_match_id(); 431 410 id->id = str_dup("root"); … … 443 422 } 444 423 445 dev_add_ref(dev);446 424 insert_dev_node(tree, dev, fun); 447 425 … … 489 467 /** Assign a driver to a device. 490 468 * 491 * @param tree Device tree492 469 * @param node The device's node in the device tree. 493 470 * @param drv The driver. 494 471 */ 495 void attach_driver(dev_ tree_t *tree, dev_node_t *dev, driver_t *drv)472 void attach_driver(dev_node_t *dev, driver_t *drv) 496 473 { 497 474 log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")", … … 499 476 500 477 fibril_mutex_lock(&drv->driver_mutex); 501 fibril_rwlock_write_lock(&tree->rwlock);502 478 503 479 dev->drv = drv; 504 480 list_append(&dev->driver_devices, &drv->devices); 505 481 506 fibril_rwlock_write_unlock(&tree->rwlock);507 fibril_mutex_unlock(&drv->driver_mutex);508 }509 510 /** Detach driver from device.511 *512 * @param tree Device tree513 * @param node The device's node in the device tree.514 * @param drv The driver.515 */516 void detach_driver(dev_tree_t *tree, dev_node_t *dev)517 {518 driver_t *drv = dev->drv;519 520 assert(drv != NULL);521 522 log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",523 dev->pfun->pathname, drv->name);524 525 fibril_mutex_lock(&drv->driver_mutex);526 fibril_rwlock_write_lock(&tree->rwlock);527 528 dev->drv = NULL;529 list_remove(&dev->driver_devices);530 531 fibril_rwlock_write_unlock(&tree->rwlock);532 482 fibril_mutex_unlock(&drv->driver_mutex); 533 483 } … … 606 556 while (link != &driver->devices.head) { 607 557 dev = list_get_instance(link, dev_node_t, driver_devices); 608 fibril_rwlock_write_lock(&tree->rwlock);609 610 558 if (dev->passed_to_driver) { 611 fibril_rwlock_write_unlock(&tree->rwlock);612 559 link = link->next; 613 560 continue; 614 561 } 615 562 616 log_msg(LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n", 617 (int)atomic_get(&dev->refcnt)); 618 dev_add_ref(dev); 563 /* 564 * We remove the device from the list to allow safe adding 565 * of new devices (no one will touch our item this way). 566 */ 567 list_remove(link); 619 568 620 569 /* … … 623 572 */ 624 573 fibril_mutex_unlock(&driver->driver_mutex); 625 fibril_rwlock_write_unlock(&tree->rwlock);626 574 627 575 add_device(driver, dev, tree); 628 629 dev_del_ref(dev);630 576 631 577 /* … … 634 580 */ 635 581 fibril_mutex_lock(&driver->driver_mutex); 582 583 /* 584 * Insert the device back. 585 * The order is not relevant here so no harm is done 586 * (actually, the order would be preserved in most cases). 587 */ 588 list_append(link, &driver->devices); 636 589 637 590 /* … … 726 679 char *loc_name = NULL; 727 680 728 assert(fibril_rwlock_is_locked(&tree->rwlock));729 730 681 asprintf(&loc_name, "%s", fun->pathname); 731 682 if (loc_name == NULL) … … 775 726 776 727 ipc_call_t answer; 777 aid_t req = async_send_2(exch, DRIVER_ DEV_ADD, dev->handle,728 aid_t req = async_send_2(exch, DRIVER_ADD_DEVICE, dev->handle, 778 729 parent_handle, &answer); 779 730 … … 832 783 833 784 /* Attach the driver to the device. */ 834 attach_driver( tree,dev, drv);785 attach_driver(dev, drv); 835 786 836 787 fibril_mutex_lock(&drv->driver_mutex); … … 846 797 add_device(drv, dev, tree); 847 798 848 fibril_mutex_lock(&drv->driver_mutex);849 fibril_mutex_unlock(&drv->driver_mutex);850 851 fibril_rwlock_write_lock(&tree->rwlock);852 if (dev->pfun != NULL) {853 dev->pfun->state = FUN_ON_LINE;854 }855 fibril_rwlock_write_unlock(&tree->rwlock);856 799 return true; 857 }858 859 int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev)860 {861 async_exch_t *exch;862 sysarg_t retval;863 driver_t *drv;864 devman_handle_t handle;865 866 assert(dev != NULL);867 868 log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev);869 870 fibril_rwlock_read_lock(&tree->rwlock);871 drv = dev->drv;872 handle = dev->handle;873 fibril_rwlock_read_unlock(&tree->rwlock);874 875 exch = async_exchange_begin(drv->sess);876 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle);877 async_exchange_end(exch);878 879 return retval;880 881 }882 883 int driver_fun_online(dev_tree_t *tree, fun_node_t *fun)884 {885 async_exch_t *exch;886 sysarg_t retval;887 driver_t *drv;888 devman_handle_t handle;889 890 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun);891 892 fibril_rwlock_read_lock(&tree->rwlock);893 894 if (fun->dev == NULL) {895 /* XXX root function? */896 fibril_rwlock_read_unlock(&tree->rwlock);897 return EINVAL;898 }899 900 drv = fun->dev->drv;901 handle = fun->handle;902 fibril_rwlock_read_unlock(&tree->rwlock);903 904 exch = async_exchange_begin(drv->sess);905 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle);906 loc_exchange_end(exch);907 908 return retval;909 }910 911 int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun)912 {913 async_exch_t *exch;914 sysarg_t retval;915 driver_t *drv;916 devman_handle_t handle;917 918 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun);919 920 fibril_rwlock_read_lock(&tree->rwlock);921 if (fun->dev == NULL) {922 /* XXX root function? */923 fibril_rwlock_read_unlock(&tree->rwlock);924 return EINVAL;925 }926 927 drv = fun->dev->drv;928 handle = fun->handle;929 fibril_rwlock_read_unlock(&tree->rwlock);930 931 exch = async_exchange_begin(drv->sess);932 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle);933 loc_exchange_end(exch);934 935 return retval;936 937 800 } 938 801 … … 963 826 if (!create_root_nodes(tree)) 964 827 return false; 965 828 966 829 /* Find suitable driver and start it. */ 967 dev_node_t *rdev = tree->root_node->child; 968 dev_add_ref(rdev); 969 int rc = assign_driver(rdev, drivers_list, tree); 970 dev_del_ref(rdev); 971 972 return rc; 830 return assign_driver(tree->root_node->child, drivers_list, tree); 973 831 } 974 832 … … 981 839 dev_node_t *create_dev_node(void) 982 840 { 983 dev_node_t *dev; 984 985 dev = calloc(1, sizeof(dev_node_t)); 986 if (dev == NULL) 987 return NULL; 988 989 atomic_set(&dev->refcnt, 0); 990 list_initialize(&dev->functions); 991 link_initialize(&dev->driver_devices); 992 link_initialize(&dev->devman_dev); 993 994 return dev; 841 dev_node_t *res = malloc(sizeof(dev_node_t)); 842 843 if (res != NULL) { 844 memset(res, 0, sizeof(dev_node_t)); 845 list_initialize(&res->functions); 846 link_initialize(&res->driver_devices); 847 link_initialize(&res->devman_dev); 848 } 849 850 return res; 995 851 } 996 852 … … 1008 864 } 1009 865 1010 /** Increase device node reference count.1011 *1012 * @param dev Device node1013 */1014 void dev_add_ref(dev_node_t *dev)1015 {1016 atomic_inc(&dev->refcnt);1017 }1018 1019 /** Decrease device node reference count.1020 *1021 * When the count drops to zero the device node is freed.1022 *1023 * @param dev Device node1024 */1025 void dev_del_ref(dev_node_t *dev)1026 {1027 if (atomic_predec(&dev->refcnt) == 0)1028 delete_dev_node(dev);1029 }1030 1031 1032 866 /** Find the device node structure of the device witch has the specified handle. 1033 867 * … … 1059 893 fibril_rwlock_read_lock(&tree->rwlock); 1060 894 dev = find_dev_node_no_lock(tree, handle); 1061 if (dev != NULL)1062 dev_add_ref(dev);1063 1064 895 fibril_rwlock_read_unlock(&tree->rwlock); 1065 896 … … 1089 920 list_get_instance(item, fun_node_t, dev_functions); 1090 921 1091 if (pos < buf_cnt) {922 if (pos < buf_cnt) 1092 923 hdl_buf[pos] = fun->handle; 1093 }1094 1095 924 pos++; 1096 925 } … … 1108 937 fun_node_t *create_fun_node(void) 1109 938 { 1110 fun_node_t *fun; 1111 1112 fun = calloc(1, sizeof(fun_node_t)); 1113 if (fun == NULL) 1114 return NULL; 1115 1116 fun->state = FUN_INIT; 1117 atomic_set(&fun->refcnt, 0); 1118 link_initialize(&fun->dev_functions); 1119 list_initialize(&fun->match_ids.ids); 1120 link_initialize(&fun->devman_fun); 1121 link_initialize(&fun->loc_fun); 1122 1123 return fun; 939 fun_node_t *res = malloc(sizeof(fun_node_t)); 940 941 if (res != NULL) { 942 memset(res, 0, sizeof(fun_node_t)); 943 link_initialize(&res->dev_functions); 944 list_initialize(&res->match_ids.ids); 945 link_initialize(&res->devman_fun); 946 link_initialize(&res->loc_fun); 947 } 948 949 return res; 1124 950 } 1125 951 … … 1139 965 } 1140 966 1141 /** Increase function node reference count.1142 *1143 * @param fun Function node1144 */1145 void fun_add_ref(fun_node_t *fun)1146 {1147 atomic_inc(&fun->refcnt);1148 }1149 1150 /** Decrease function node reference count.1151 *1152 * When the count drops to zero the function node is freed.1153 *1154 * @param fun Function node1155 */1156 void fun_del_ref(fun_node_t *fun)1157 {1158 if (atomic_predec(&fun->refcnt) == 0)1159 delete_fun_node(fun);1160 }1161 1162 967 /** Find the function node with the specified handle. 1163 968 * … … 1170 975 unsigned long key = handle; 1171 976 link_t *link; 1172 fun_node_t *fun;1173 977 1174 978 assert(fibril_rwlock_is_locked(&tree->rwlock)); … … 1178 982 return NULL; 1179 983 1180 fun = hash_table_get_instance(link, fun_node_t, devman_fun); 1181 1182 return fun; 984 return hash_table_get_instance(link, fun_node_t, devman_fun); 1183 985 } 1184 986 … … 1194 996 1195 997 fibril_rwlock_read_lock(&tree->rwlock); 1196 1197 998 fun = find_fun_node_no_lock(tree, handle); 1198 if (fun != NULL)1199 fun_add_ref(fun);1200 1201 999 fibril_rwlock_read_unlock(&tree->rwlock); 1202 1000 … … 1206 1004 /** Create and set device's full path in device tree. 1207 1005 * 1208 * @param tree Device tree1209 1006 * @param node The device's device node. 1210 1007 * @param parent The parent device node. … … 1212 1009 * resources etc.). 1213 1010 */ 1214 static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent) 1215 { 1216 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1011 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1012 { 1217 1013 assert(fun->name != NULL); 1218 1014 … … 1241 1037 * 1242 1038 * @param tree The device tree. 1243 * @param dev The newly added device node. 1244 * @param pfun The parent function node. 1039 * @param node The newly added device node. 1040 * @param dev_name The name of the newly added device. 1041 * @param parent The parent device node. 1245 1042 * 1246 1043 * @return True on success, false otherwise (insufficient resources … … 1249 1046 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1250 1047 { 1048 assert(dev != NULL); 1049 assert(tree != NULL); 1251 1050 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1252 1051 … … 1266 1065 } 1267 1066 1268 /** Remove device from device tree.1269 *1270 * @param tree Device tree1271 * @param dev Device node1272 */1273 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)1274 {1275 assert(fibril_rwlock_is_write_locked(&tree->rwlock));1276 1277 log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev);1278 1279 /* Remove node from the handle-to-node map. */1280 unsigned long key = dev->handle;1281 hash_table_remove(&tree->devman_devices, &key, 1);1282 1283 /* Unlink from parent function. */1284 dev->pfun->child = NULL;1285 dev->pfun = NULL;1286 1287 dev->state = DEVICE_REMOVED;1288 }1289 1290 1291 1067 /** Insert new function into device tree. 1292 1068 * 1293 1069 * @param tree The device tree. 1294 * @param funThe newly added function node.1295 * @param fun_name The name of the newly added function.1296 * @param devOwning device node.1070 * @param node The newly added function node. 1071 * @param dev_name The name of the newly added function. 1072 * @param parent Owning device node. 1297 1073 * 1298 1074 * @return True on success, false otherwise (insufficient resources … … 1304 1080 fun_node_t *pfun; 1305 1081 1082 assert(fun != NULL); 1083 assert(tree != NULL); 1306 1084 assert(fun_name != NULL); 1307 1085 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); … … 1314 1092 1315 1093 fun->name = fun_name; 1316 if (!set_fun_path( tree,fun, pfun)) {1094 if (!set_fun_path(fun, pfun)) { 1317 1095 return false; 1318 1096 } … … 1338 1116 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun) 1339 1117 { 1118 assert(tree != NULL); 1119 assert(fun != NULL); 1340 1120 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1341 1121 … … 1347 1127 if (fun->dev != NULL) 1348 1128 list_remove(&fun->dev_functions); 1349 1350 fun->dev = NULL;1351 fun->state = FUN_REMOVED;1352 1129 } 1353 1130 … … 1371 1148 1372 1149 fun_node_t *fun = tree->root_node; 1373 fun_add_ref(fun);1374 1150 /* 1375 1151 * Relative path to the function from its parent (but with '/' at the … … 1389 1165 } 1390 1166 1391 fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1); 1392 fun_del_ref(fun); 1393 fun = cfun; 1167 fun = find_node_child(fun, rel_path + 1); 1394 1168 1395 1169 if (cont) { … … 1409 1183 * Device tree rwlock should be held at least for reading. 1410 1184 * 1411 * @param tree Device tree1412 1185 * @param dev Device the function belongs to. 1413 1186 * @param name Function name (not path). … … 1415 1188 * @retval NULL No function with given name. 1416 1189 */ 1417 fun_node_t *find_fun_node_in_device(dev_ tree_t *tree, dev_node_t *dev,1418 const char *name) 1419 { 1190 fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name) 1191 { 1192 assert(dev != NULL); 1420 1193 assert(name != NULL); 1421 assert(fibril_rwlock_is_locked(&tree->rwlock));1422 1194 1423 1195 fun_node_t *fun; … … 1426 1198 fun = list_get_instance(link, fun_node_t, dev_functions); 1427 1199 1428 if (str_cmp(name, fun->name) == 0) { 1429 fun_add_ref(fun); 1200 if (str_cmp(name, fun->name) == 0) 1430 1201 return fun; 1431 }1432 1202 } 1433 1203 … … 1439 1209 * Device tree rwlock should be held at least for reading. 1440 1210 * 1441 * @param tree Device tree1442 1211 * @param parent The parent function node. 1443 1212 * @param name The name of the child function. 1444 1213 * @return The child function node. 1445 1214 */ 1446 static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun, 1447 const char *name) 1448 { 1449 return find_fun_node_in_device(tree, pfun->child, name); 1215 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1216 { 1217 return find_fun_node_in_device(pfun->child, name); 1450 1218 } 1451 1219 … … 1460 1228 fibril_rwlock_read_lock(&tree->rwlock); 1461 1229 link = hash_table_find(&tree->loc_functions, &key); 1462 if (link != NULL) {1230 if (link != NULL) 1463 1231 fun = hash_table_get_instance(link, fun_node_t, loc_fun); 1464 fun_add_ref(fun);1465 }1466 1232 fibril_rwlock_read_unlock(&tree->rwlock); 1467 1233 … … 1471 1237 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1472 1238 { 1473 assert(fibril_rwlock_is_write_locked(&tree->rwlock));1474 1475 1239 unsigned long key = (unsigned long) fun->service_id; 1240 fibril_rwlock_write_lock(&tree->rwlock); 1476 1241 hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun); 1242 fibril_rwlock_write_unlock(&tree->rwlock); 1477 1243 } 1478 1244
Note:
See TracChangeset
for help on using the changeset viewer.
