Changes in uspace/srv/devman/devman.c [80a96d2:45059d6b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
r80a96d2 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 int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev)883 {884 async_exch_t *exch;885 sysarg_t retval;886 driver_t *drv;887 devman_handle_t handle;888 889 assert(dev != NULL);890 891 log_msg(LVL_DEBUG, "driver_dev_gone(%p)", dev);892 893 fibril_rwlock_read_lock(&tree->rwlock);894 drv = dev->drv;895 handle = dev->handle;896 fibril_rwlock_read_unlock(&tree->rwlock);897 898 exch = async_exchange_begin(drv->sess);899 retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle);900 async_exchange_end(exch);901 902 return retval;903 }904 905 int driver_fun_online(dev_tree_t *tree, fun_node_t *fun)906 {907 async_exch_t *exch;908 sysarg_t retval;909 driver_t *drv;910 devman_handle_t handle;911 912 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun);913 914 fibril_rwlock_read_lock(&tree->rwlock);915 916 if (fun->dev == NULL) {917 /* XXX root function? */918 fibril_rwlock_read_unlock(&tree->rwlock);919 return EINVAL;920 }921 922 drv = fun->dev->drv;923 handle = fun->handle;924 fibril_rwlock_read_unlock(&tree->rwlock);925 926 exch = async_exchange_begin(drv->sess);927 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle);928 loc_exchange_end(exch);929 930 return retval;931 }932 933 int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun)934 {935 async_exch_t *exch;936 sysarg_t retval;937 driver_t *drv;938 devman_handle_t handle;939 940 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun);941 942 fibril_rwlock_read_lock(&tree->rwlock);943 if (fun->dev == NULL) {944 /* XXX root function? */945 fibril_rwlock_read_unlock(&tree->rwlock);946 return EINVAL;947 }948 949 drv = fun->dev->drv;950 handle = fun->handle;951 fibril_rwlock_read_unlock(&tree->rwlock);952 953 exch = async_exchange_begin(drv->sess);954 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle);955 loc_exchange_end(exch);956 957 return retval;958 959 800 } 960 801 … … 985 826 if (!create_root_nodes(tree)) 986 827 return false; 987 828 988 829 /* Find suitable driver and start it. */ 989 dev_node_t *rdev = tree->root_node->child; 990 dev_add_ref(rdev); 991 int rc = assign_driver(rdev, drivers_list, tree); 992 dev_del_ref(rdev); 993 994 return rc; 830 return assign_driver(tree->root_node->child, drivers_list, tree); 995 831 } 996 832 … … 1003 839 dev_node_t *create_dev_node(void) 1004 840 { 1005 dev_node_t *dev; 1006 1007 dev = calloc(1, sizeof(dev_node_t)); 1008 if (dev == NULL) 1009 return NULL; 1010 1011 atomic_set(&dev->refcnt, 0); 1012 list_initialize(&dev->functions); 1013 link_initialize(&dev->driver_devices); 1014 link_initialize(&dev->devman_dev); 1015 1016 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; 1017 851 } 1018 852 … … 1030 864 } 1031 865 1032 /** Increase device node reference count.1033 *1034 * @param dev Device node1035 */1036 void dev_add_ref(dev_node_t *dev)1037 {1038 atomic_inc(&dev->refcnt);1039 }1040 1041 /** Decrease device node reference count.1042 *1043 * When the count drops to zero the device node is freed.1044 *1045 * @param dev Device node1046 */1047 void dev_del_ref(dev_node_t *dev)1048 {1049 if (atomic_predec(&dev->refcnt) == 0)1050 delete_dev_node(dev);1051 }1052 1053 1054 866 /** Find the device node structure of the device witch has the specified handle. 1055 867 * … … 1081 893 fibril_rwlock_read_lock(&tree->rwlock); 1082 894 dev = find_dev_node_no_lock(tree, handle); 1083 if (dev != NULL)1084 dev_add_ref(dev);1085 1086 895 fibril_rwlock_read_unlock(&tree->rwlock); 1087 896 … … 1111 920 list_get_instance(item, fun_node_t, dev_functions); 1112 921 1113 if (pos < buf_cnt) {922 if (pos < buf_cnt) 1114 923 hdl_buf[pos] = fun->handle; 1115 }1116 1117 924 pos++; 1118 925 } … … 1130 937 fun_node_t *create_fun_node(void) 1131 938 { 1132 fun_node_t *fun; 1133 1134 fun = calloc(1, sizeof(fun_node_t)); 1135 if (fun == NULL) 1136 return NULL; 1137 1138 fun->state = FUN_INIT; 1139 atomic_set(&fun->refcnt, 0); 1140 link_initialize(&fun->dev_functions); 1141 list_initialize(&fun->match_ids.ids); 1142 link_initialize(&fun->devman_fun); 1143 link_initialize(&fun->loc_fun); 1144 1145 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; 1146 950 } 1147 951 … … 1161 965 } 1162 966 1163 /** Increase function node reference count.1164 *1165 * @param fun Function node1166 */1167 void fun_add_ref(fun_node_t *fun)1168 {1169 atomic_inc(&fun->refcnt);1170 }1171 1172 /** Decrease function node reference count.1173 *1174 * When the count drops to zero the function node is freed.1175 *1176 * @param fun Function node1177 */1178 void fun_del_ref(fun_node_t *fun)1179 {1180 if (atomic_predec(&fun->refcnt) == 0)1181 delete_fun_node(fun);1182 }1183 1184 967 /** Find the function node with the specified handle. 1185 968 * … … 1192 975 unsigned long key = handle; 1193 976 link_t *link; 1194 fun_node_t *fun;1195 977 1196 978 assert(fibril_rwlock_is_locked(&tree->rwlock)); … … 1200 982 return NULL; 1201 983 1202 fun = hash_table_get_instance(link, fun_node_t, devman_fun); 1203 1204 return fun; 984 return hash_table_get_instance(link, fun_node_t, devman_fun); 1205 985 } 1206 986 … … 1216 996 1217 997 fibril_rwlock_read_lock(&tree->rwlock); 1218 1219 998 fun = find_fun_node_no_lock(tree, handle); 1220 if (fun != NULL)1221 fun_add_ref(fun);1222 1223 999 fibril_rwlock_read_unlock(&tree->rwlock); 1224 1000 … … 1228 1004 /** Create and set device's full path in device tree. 1229 1005 * 1230 * @param tree Device tree1231 1006 * @param node The device's device node. 1232 1007 * @param parent The parent device node. … … 1234 1009 * resources etc.). 1235 1010 */ 1236 static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent) 1237 { 1238 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1011 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1012 { 1239 1013 assert(fun->name != NULL); 1240 1014 … … 1263 1037 * 1264 1038 * @param tree The device tree. 1265 * @param dev The newly added device node. 1266 * @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. 1267 1042 * 1268 1043 * @return True on success, false otherwise (insufficient resources … … 1271 1046 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1272 1047 { 1048 assert(dev != NULL); 1049 assert(tree != NULL); 1273 1050 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1274 1051 … … 1288 1065 } 1289 1066 1290 /** Remove device from device tree.1291 *1292 * @param tree Device tree1293 * @param dev Device node1294 */1295 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)1296 {1297 assert(fibril_rwlock_is_write_locked(&tree->rwlock));1298 1299 log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev);1300 1301 /* Remove node from the handle-to-node map. */1302 unsigned long key = dev->handle;1303 hash_table_remove(&tree->devman_devices, &key, 1);1304 1305 /* Unlink from parent function. */1306 dev->pfun->child = NULL;1307 dev->pfun = NULL;1308 1309 dev->state = DEVICE_REMOVED;1310 }1311 1312 1313 1067 /** Insert new function into device tree. 1314 1068 * 1315 1069 * @param tree The device tree. 1316 * @param funThe newly added function node.1317 * @param fun_name The name of the newly added function.1318 * @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. 1319 1073 * 1320 1074 * @return True on success, false otherwise (insufficient resources … … 1326 1080 fun_node_t *pfun; 1327 1081 1082 assert(fun != NULL); 1083 assert(tree != NULL); 1328 1084 assert(fun_name != NULL); 1329 1085 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); … … 1336 1092 1337 1093 fun->name = fun_name; 1338 if (!set_fun_path( tree,fun, pfun)) {1094 if (!set_fun_path(fun, pfun)) { 1339 1095 return false; 1340 1096 } … … 1360 1116 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun) 1361 1117 { 1118 assert(tree != NULL); 1119 assert(fun != NULL); 1362 1120 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1363 1121 … … 1369 1127 if (fun->dev != NULL) 1370 1128 list_remove(&fun->dev_functions); 1371 1372 fun->dev = NULL;1373 fun->state = FUN_REMOVED;1374 1129 } 1375 1130 … … 1393 1148 1394 1149 fun_node_t *fun = tree->root_node; 1395 fun_add_ref(fun);1396 1150 /* 1397 1151 * Relative path to the function from its parent (but with '/' at the … … 1411 1165 } 1412 1166 1413 fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1); 1414 fun_del_ref(fun); 1415 fun = cfun; 1167 fun = find_node_child(fun, rel_path + 1); 1416 1168 1417 1169 if (cont) { … … 1431 1183 * Device tree rwlock should be held at least for reading. 1432 1184 * 1433 * @param tree Device tree1434 1185 * @param dev Device the function belongs to. 1435 1186 * @param name Function name (not path). … … 1437 1188 * @retval NULL No function with given name. 1438 1189 */ 1439 fun_node_t *find_fun_node_in_device(dev_ tree_t *tree, dev_node_t *dev,1440 const char *name) 1441 { 1190 fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name) 1191 { 1192 assert(dev != NULL); 1442 1193 assert(name != NULL); 1443 assert(fibril_rwlock_is_locked(&tree->rwlock));1444 1194 1445 1195 fun_node_t *fun; … … 1448 1198 fun = list_get_instance(link, fun_node_t, dev_functions); 1449 1199 1450 if (str_cmp(name, fun->name) == 0) { 1451 fun_add_ref(fun); 1200 if (str_cmp(name, fun->name) == 0) 1452 1201 return fun; 1453 }1454 1202 } 1455 1203 … … 1461 1209 * Device tree rwlock should be held at least for reading. 1462 1210 * 1463 * @param tree Device tree1464 1211 * @param parent The parent function node. 1465 1212 * @param name The name of the child function. 1466 1213 * @return The child function node. 1467 1214 */ 1468 static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun, 1469 const char *name) 1470 { 1471 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); 1472 1218 } 1473 1219 … … 1482 1228 fibril_rwlock_read_lock(&tree->rwlock); 1483 1229 link = hash_table_find(&tree->loc_functions, &key); 1484 if (link != NULL) {1230 if (link != NULL) 1485 1231 fun = hash_table_get_instance(link, fun_node_t, loc_fun); 1486 fun_add_ref(fun);1487 }1488 1232 fibril_rwlock_read_unlock(&tree->rwlock); 1489 1233 … … 1493 1237 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1494 1238 { 1495 assert(fibril_rwlock_is_write_locked(&tree->rwlock));1496 1497 1239 unsigned long key = (unsigned long) fun->service_id; 1240 fibril_rwlock_write_lock(&tree->rwlock); 1498 1241 hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun); 1242 fibril_rwlock_write_unlock(&tree->rwlock); 1499 1243 } 1500 1244
Note:
See TracChangeset
for help on using the changeset viewer.