Changeset d9fae235 in mainline for kernel/generic/src/sysinfo/sysinfo.c
- Timestamp:
- 2010-04-17T01:28:38Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9d6bfa5
- Parents:
- 9256ad29
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/sysinfo/sysinfo.c
r9256ad29 rd9fae235 37 37 #include <print.h> 38 38 #include <syscall/copy.h> 39 #include <errno.h> 40 41 #define SYSINFO_MAX_PATH 2048 39 42 40 43 bool fb_exported = false; 41 sysinfo_item_t *_root = NULL; 42 43 static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree) 44 { 45 if (subtree == NULL) 46 return NULL; 47 48 while (subtree != NULL) { 49 int i = 0; 50 char *a = (char *) name; 51 char *b = subtree->name; 52 53 while ((a[i] == b[i]) && (b[i])) 44 45 static sysinfo_item_t *global_root = NULL; 46 static slab_cache_t *sysinfo_item_slab; 47 48 static int sysinfo_item_constructor(void *obj, int kmflag) 49 { 50 sysinfo_item_t *item = (sysinfo_item_t *) obj; 51 52 item->name = NULL; 53 item->val_type = SYSINFO_VAL_UNDEFINED; 54 item->subtree_type = SYSINFO_SUBTREE_NONE; 55 item->next = NULL; 56 57 return 0; 58 } 59 60 static int sysinfo_item_destructor(void *obj) 61 { 62 sysinfo_item_t *item = (sysinfo_item_t *) obj; 63 64 if (item->name != NULL) 65 free(item->name); 66 67 return 0; 68 } 69 70 void sysinfo_init(void) 71 { 72 sysinfo_item_slab = slab_cache_create("sysinfo_item_slab", 73 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor, 74 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED); 75 } 76 77 static sysinfo_item_t *sysinfo_find_item(const char *name, 78 sysinfo_item_t *subtree) 79 { 80 sysinfo_item_t *cur = subtree; 81 82 while (cur != NULL) { 83 size_t i = 0; 84 85 /* Compare name with path */ 86 while ((cur->name[i] != 0) && (name[i] == cur->name[i])) 54 87 i++; 55 88 56 if ((!a[i]) && (!b[i])) /* Last name in path matches */ 57 return subtree; 58 59 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */ 60 if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE) 61 return sysinfo_find_item(a + i + 1, subtree->subinfo.table); 89 /* Check for perfect name and path match */ 90 if ((name[i] == 0) && (cur->name[i] == 0)) 91 return cur; 92 93 /* Partial match up to the delimiter */ 94 if ((name[i] == '.') && (cur->name[i] == 0)) { 95 /* Look into the subtree */ 96 switch (cur->subtree_type) { 97 case SYSINFO_SUBTREE_TABLE: 98 /* Recursively find in subtree */ 99 return sysinfo_find_item(name + i + 1, cur->subtree.table); 100 case SYSINFO_SUBTREE_FUNCTION: 101 /* Get generated item */ 102 return cur->subtree.find_item(name + i + 1); 103 default: 104 /* Not found */ 105 return NULL; 106 } 107 } 108 109 cur = cur->next; 110 } 111 112 return NULL; 113 } 114 115 static sysinfo_item_t *sysinfo_create_path(const char *name, 116 sysinfo_item_t **psubtree) 117 { 118 if (*psubtree == NULL) { 119 /* No parent */ 120 121 size_t i = 0; 122 123 /* Find the first delimiter in name */ 124 while ((name[i] != 0) && (name[i] != '.')) 125 i++; 126 127 *psubtree = 128 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0); 129 ASSERT(*psubtree); 130 131 /* Fill in item name up to the delimiter */ 132 (*psubtree)->name = str_ndup(name, i); 133 ASSERT((*psubtree)->name); 134 135 /* Create subtree items */ 136 if (name[i] == '.') { 137 (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE; 138 return sysinfo_create_path(name + i + 1, 139 &((*psubtree)->subtree.table)); 140 } 141 142 /* No subtree needs to be created */ 143 return *psubtree; 144 } 145 146 sysinfo_item_t *cur = *psubtree; 147 148 while (cur != NULL) { 149 size_t i = 0; 150 151 /* Compare name with path */ 152 while ((cur->name[i] != 0) && (name[i] == cur->name[i])) 153 i++; 154 155 /* Check for perfect name and path match 156 * -> item is already present. 157 */ 158 if ((name[i] == 0) && (cur->name[i] == 0)) 159 return cur; 160 161 /* Partial match up to the delimiter */ 162 if ((name[i] == '.') && (cur->name[i] == 0)) { 163 switch (cur->subtree_type) { 164 case SYSINFO_SUBTREE_NONE: 165 /* No subtree yet, create one */ 166 cur->subtree_type = SYSINFO_SUBTREE_TABLE; 167 return sysinfo_create_path(name + i + 1, 168 &(cur->subtree.table)); 169 case SYSINFO_SUBTREE_TABLE: 170 /* Subtree already created, add new sibling */ 171 return sysinfo_create_path(name + i + 1, 172 &(cur->subtree.table)); 173 default: 174 /* Subtree items handled by a function, this 175 * cannot be overriden. 176 */ 177 return NULL; 178 } 179 } 180 181 /* No match and no more siblings to check 182 * -> create a new sibling item. 183 */ 184 if (cur->next == NULL) { 185 /* Find the first delimiter in name */ 186 i = 0; 187 while ((name[i] != 0) && (name[i] != '.')) 188 i++; 62 189 63 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 64 // return NULL; 190 sysinfo_item_t *item = 191 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0); 192 ASSERT(item); 65 193 66 return NULL; /* No subinfo */ 67 } 68 /* No matches try next */ 69 subtree = subtree->next; 70 } 71 return NULL; 72 } 73 74 static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree) 75 { 76 sysinfo_item_t *subtree; 77 subtree = *psubtree; 78 79 if (subtree == NULL) { 80 sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0); 81 int i = 0, j; 194 cur->next = item; 82 195 83 ASSERT(item); 84 *psubtree = item; 85 item->next = NULL; 86 item->val_type = SYSINFO_VAL_UNDEFINED; 87 item->subinfo.table = NULL; 88 89 while (name[i] && (name[i] != '.')) 90 i++; 196 /* Fill in item name up to the delimiter */ 197 item->name = str_ndup(name, i); 198 ASSERT(item->name); 91 199 92 item->name = malloc(i, 0); 93 ASSERT(item->name); 94 95 for (j = 0; j < i; j++) 96 item->name[j] = name[j]; 97 item->name[j] = 0; 98 99 if (name[i]) { /* =='.' */ 100 item->subinfo_type = SYSINFO_SUBINFO_TABLE; 101 return sysinfo_create_path(name + i + 1, &(item->subinfo.table)); 102 } 103 item->subinfo_type = SYSINFO_SUBINFO_NONE; 104 return item; 105 } 106 107 while (subtree != NULL) { 108 int i = 0, j; 109 char *a = (char *) name; 110 char *b = subtree->name; 111 112 while ((a[i] == b[i]) && (b[i])) 113 i++; 114 115 if ((!a[i]) && (!b[i])) /* Last name in path matches */ 116 return subtree; 117 118 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */ 119 if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE) 120 return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table)); 121 122 if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) { 123 subtree->subinfo_type = SYSINFO_SUBINFO_TABLE; 124 return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table)); 200 /* Create subtree items */ 201 if (name[i] == '.') { 202 item->subtree_type = SYSINFO_SUBTREE_TABLE; 203 return sysinfo_create_path(name + i + 1, 204 &(item->subtree.table)); 125 205 } 126 206 127 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 128 // return NULL; 129 130 return NULL; 131 } 132 /* No matches try next or create new*/ 133 if (subtree->next == NULL) { 134 sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0); 135 136 ASSERT(item); 137 subtree->next = item; 138 item->next = NULL; 139 item->val_type = SYSINFO_VAL_UNDEFINED; 140 item->subinfo.table = NULL; 141 142 i = 0; 143 while (name[i] && (name[i] != '.')) 144 i++; 145 146 item->name = malloc(i, 0); 147 ASSERT(item->name); 148 149 for (j = 0; j < i; j++) 150 item->name[j] = name[j]; 151 152 item->name[j] = 0; 153 154 if(name[i]) { /* =='.' */ 155 item->subinfo_type = SYSINFO_SUBINFO_TABLE; 156 return sysinfo_create_path(name + i + 1, &(item->subinfo.table)); 157 } 158 item->subinfo_type = SYSINFO_SUBINFO_NONE; 207 /* No subtree needs to be created */ 159 208 return item; 160 } else 161 subtree = subtree->next; 162 } 163 164 panic("Not reached."); 209 } 210 211 /* Get next sibling */ 212 cur = cur->next; 213 } 214 215 /* Unreachable */ 216 ASSERT(false); 165 217 return NULL; 166 218 } 167 219 168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val) 169 { 170 if (root == NULL) 171 root = &_root; 172 173 /* If already created create only returns pointer 174 If not, create it */ 220 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, 221 unative_t val) 222 { 223 if (root == NULL) 224 root = &global_root; 225 175 226 sysinfo_item_t *item = sysinfo_create_path(name, root); 176 177 if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ 178 item->val.val = val; 227 if (item != NULL) { 179 228 item->val_type = SYSINFO_VAL_VAL; 180 }181 }182 183 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn) 184 { 185 if (root == NULL)186 root = &_root; 187 188 /* If already created create only returns pointer189 If not, create it */229 item->val.val = val; 230 } 231 } 232 233 void sysinfo_set_item_data(const char *name, sysinfo_item_t **root, 234 void *data, size_t size) 235 { 236 if (root == NULL) 237 root = &global_root; 238 190 239 sysinfo_item_t *item = sysinfo_create_path(name, root); 191 192 if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */ 193 item->val.fn = fn; 194 item->val_type = SYSINFO_VAL_FUNCTION; 195 } 196 } 197 240 if (item != NULL) { 241 item->val_type = SYSINFO_VAL_DATA; 242 item->val.data.data = data; 243 item->val.data.size = size; 244 } 245 } 246 247 void sysinfo_set_item_val_fn(const char *name, sysinfo_item_t **root, 248 sysinfo_fn_val_t fn) 249 { 250 if (root == NULL) 251 root = &global_root; 252 253 sysinfo_item_t *item = sysinfo_create_path(name, root); 254 if (item != NULL) { 255 item->val_type = SYSINFO_VAL_FUNCTION_VAL; 256 item->val.fn_val = fn; 257 } 258 } 259 260 void sysinfo_set_item_data_fn(const char *name, sysinfo_item_t **root, 261 sysinfo_fn_data_t fn) 262 { 263 if (root == NULL) 264 root = &global_root; 265 266 sysinfo_item_t *item = sysinfo_create_path(name, root); 267 if (item != NULL) { 268 item->val_type = SYSINFO_VAL_FUNCTION_DATA; 269 item->val.fn_data = fn; 270 } 271 } 198 272 199 273 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root) 200 274 { 201 275 if (root == NULL) 202 root = &_root; 203 204 /* If already created create only returns pointer 205 If not, create it */ 276 root = &global_root; 277 206 278 sysinfo_item_t *item = sysinfo_create_path(name, root); 207 208 279 if (item != NULL) 209 280 item->val_type = SYSINFO_VAL_UNDEFINED; 210 281 } 211 282 212 213 void sysinfo_dump(sysinfo_item_t **proot, int depth) 214 { 215 sysinfo_item_t *root; 283 static void sysinfo_indent(unsigned int depth) 284 { 285 unsigned int i; 286 for (i = 0; i < depth; i++) 287 printf(" "); 288 } 289 290 void sysinfo_dump(sysinfo_item_t **proot, unsigned int depth) 291 { 216 292 if (proot == NULL) 217 proot = &_root; 218 219 root = *proot; 220 221 while (root != NULL) { 222 int i; 223 unative_t val = 0; 224 const char *vtype = NULL; 225 226 227 for (i = 0; i < depth; i++) 228 printf(" "); 229 230 switch (root->val_type) { 293 proot = &global_root; 294 295 sysinfo_item_t *cur = *proot; 296 297 while (cur != NULL) { 298 sysinfo_indent(depth); 299 300 unative_t val; 301 size_t size; 302 303 switch (cur->val_type) { 231 304 case SYSINFO_VAL_UNDEFINED: 232 val = 0; 233 vtype = "UND"; 305 printf("+ %s\n", cur->name); 234 306 break; 235 307 case SYSINFO_VAL_VAL: 236 val = root->val.val; 237 vtype = "VAL"; 238 break; 239 case SYSINFO_VAL_FUNCTION: 240 val = ((sysinfo_val_fn_t) (root->val.fn)) (root); 241 vtype = "FUN"; 242 break; 243 } 244 245 printf("%s %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val, 246 val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ? 247 "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ? 248 "TAB" : "FUN")); 249 250 if (root->subinfo_type == SYSINFO_SUBINFO_TABLE) 251 sysinfo_dump(&(root -> subinfo.table), depth + 1); 252 253 root = root->next; 254 } 255 } 256 257 sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root) 258 { 259 // TODO: Implement Subsystem subinfo (by function implemented subinfo) 260 261 sysinfo_rettype_t ret = {0, false}; 262 263 if (root == NULL) 264 root = &_root; 308 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name, 309 cur->val.val, cur->val.val); 310 break; 311 case SYSINFO_VAL_DATA: 312 printf("+ %s (%" PRIs" bytes)\n", cur->name, 313 cur->val.data.size); 314 break; 315 case SYSINFO_VAL_FUNCTION_VAL: 316 val = cur->val.fn_val(cur); 317 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n", 318 cur->name, val, val); 319 break; 320 case SYSINFO_VAL_FUNCTION_DATA: 321 cur->val.fn_data(cur, &size); 322 printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name, 323 size); 324 break; 325 default: 326 printf("+ %s [unknown]\n", cur->name); 327 } 328 329 switch (cur->subtree_type) { 330 case SYSINFO_SUBTREE_NONE: 331 break; 332 case SYSINFO_SUBTREE_TABLE: 333 sysinfo_dump(&(cur->subtree.table), depth + 1); 334 break; 335 case SYSINFO_SUBTREE_FUNCTION: 336 sysinfo_indent(depth + 1); 337 printf(" [generated subtree]\n"); 338 break; 339 default: 340 sysinfo_indent(depth + 1); 341 printf(" [unknown subtree]\n"); 342 } 343 344 cur = cur->next; 345 } 346 } 347 348 sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root) 349 { 350 if (root == NULL) 351 root = &global_root; 265 352 266 353 sysinfo_item_t *item = sysinfo_find_item(name, *root); 354 sysinfo_return_t ret; 267 355 268 356 if (item != NULL) { 269 if (item->val_type == SYSINFO_VAL_UNDEFINED)270 return ret;271 else272 ret.valid = true;273 274 if (item->val_type == SYSINFO_VAL_VAL)357 switch (item->val_type) { 358 case SYSINFO_VAL_UNDEFINED: 359 ret.tag = SYSINFO_VAL_UNDEFINED; 360 break; 361 case SYSINFO_VAL_VAL: 362 ret.tag = SYSINFO_VAL_VAL; 275 363 ret.val = item->val.val; 276 else 277 ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item); 278 } 364 break; 365 case SYSINFO_VAL_DATA: 366 ret.tag = SYSINFO_VAL_DATA; 367 ret.data = item->val.data; 368 break; 369 case SYSINFO_VAL_FUNCTION_VAL: 370 ret.tag = SYSINFO_VAL_VAL; 371 ret.val = item->val.fn_val(item); 372 break; 373 case SYSINFO_VAL_FUNCTION_DATA: 374 ret.tag = SYSINFO_VAL_DATA; 375 ret.data.data = item->val.fn_data(item, &ret.data.size); 376 break; 377 } 378 } else 379 ret.tag = SYSINFO_VAL_UNDEFINED; 380 279 381 return ret; 280 382 } 281 383 282 #define SYSINFO_MAX_LEN 1024 283 284 unative_t sys_sysinfo_valid(unative_t ptr, unative_t len) 285 { 286 char *str; 287 sysinfo_rettype_t ret = {0, 0}; 288 289 if (len > SYSINFO_MAX_LEN) 290 return ret.valid; 291 str = malloc(len + 1, 0); 292 293 ASSERT(str); 294 if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) 295 ret = sysinfo_get_val(str, NULL); 296 297 free(str); 298 return ret.valid; 299 } 300 301 unative_t sys_sysinfo_value(unative_t ptr, unative_t len) 302 { 303 char *str; 304 sysinfo_rettype_t ret = {0, 0}; 305 306 if (len > SYSINFO_MAX_LEN) 307 return ret.val; 308 str = malloc(len + 1, 0); 309 310 ASSERT(str); 311 if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) 312 ret = sysinfo_get_val(str, NULL); 313 314 free(str); 315 return ret.val; 384 static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size) 385 { 386 sysinfo_return_t ret; 387 ret.tag = SYSINFO_VAL_UNDEFINED; 388 389 if (size > SYSINFO_MAX_PATH) 390 return ret; 391 392 char *path = (char *) malloc(size + 1, 0); 393 ASSERT(path); 394 395 if ((copy_from_uspace(path, ptr, size + 1) == 0) 396 && (path[size] == 0)) { 397 ret = sysinfo_get_item(path, NULL); 398 free(path); 399 } 400 401 return ret; 402 } 403 404 unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size) 405 { 406 return (unative_t) sysinfo_get_item_uspace(path_ptr, path_size).tag; 407 } 408 409 unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size, 410 void *value_ptr) 411 { 412 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 413 414 if (ret.tag != SYSINFO_VAL_VAL) 415 return (unative_t) EINVAL; 416 417 return (unative_t) copy_to_uspace(value_ptr, &ret.val, 418 sizeof(ret.val)); 419 } 420 421 unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size, 422 void *size_ptr) 423 { 424 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 425 426 if (ret.tag != SYSINFO_VAL_DATA) 427 return (unative_t) EINVAL; 428 429 return (unative_t) copy_to_uspace(size_ptr, &ret.data.size, 430 sizeof(ret.data.size)); 431 } 432 433 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size, 434 void *buffer_ptr, size_t buffer_size) 435 { 436 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size); 437 438 if (ret.tag != SYSINFO_VAL_DATA) 439 return (unative_t) EINVAL; 440 441 if (ret.data.size != buffer_size) 442 return ENOMEM; 443 444 return (unative_t) copy_to_uspace(buffer_ptr, ret.data.data, 445 ret.data.size); 316 446 } 317 447
Note:
See TracChangeset
for help on using the changeset viewer.