Changeset f4f866c in mainline for kernel/generic
- Timestamp:
- 2010-04-23T21:42:26Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6c39a907
- Parents:
- 38aaacc2 (diff), 80badbe (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- kernel/generic
- Files:
-
- 2 added
- 32 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/cpu.h
r38aaacc2 rf4f866c 68 68 are disabled. */ 69 69 70 bool idle; 71 uint64_t idle_ticks; 72 uint64_t busy_ticks; 73 70 74 /** 71 75 * Processor ID assigned by kernel. … … 73 77 unsigned int id; 74 78 75 intactive;79 bool active; 76 80 int tlb_active; 77 81 -
kernel/generic/include/func.h
r38aaacc2 rf4f866c 43 43 extern void halt(void) __attribute__((noreturn)); 44 44 extern unative_t atoi(const char *text); 45 extern void order(const uint64_t val, uint64_t *rv, char *suffix);46 45 47 46 #endif -
kernel/generic/include/ipc/sysipc.h
r38aaacc2 rf4f866c 57 57 unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid, 58 58 ipc_data_t *data, int mode); 59 unative_t sys_ipc_hangup( int phoneid);59 unative_t sys_ipc_hangup(unative_t phoneid); 60 60 unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, 61 61 irq_code_t *ucode); -
kernel/generic/include/mm/frame.h
r38aaacc2 rf4f866c 169 169 extern bool zone_merge(size_t, size_t); 170 170 extern void zone_merge_all(void); 171 extern uint64_t zone_total_size(void); 171 extern uint64_t zones_total_size(void); 172 extern void zones_stats(uint64_t *, uint64_t *, uint64_t *, uint64_t *); 172 173 173 174 /* 174 175 * Console functions 175 176 */ 176 extern void zone _print_list(void);177 extern void zones_print_list(void); 177 178 extern void zone_print_one(size_t); 178 179 -
kernel/generic/include/print.h
r38aaacc2 rf4f866c 39 39 #include <stdarg.h> 40 40 41 #define EOF (-1)41 #define EOF (-1) 42 42 43 43 extern int puts(const char *s); -
kernel/generic/include/printf/printf_core.h
r38aaacc2 rf4f866c 51 51 } printf_spec_t; 52 52 53 int printf_core(const char *fmt, printf_spec_t *ps, va_list ap);53 extern int printf_core(const char *fmt, printf_spec_t *ps, va_list ap); 54 54 55 55 #endif -
kernel/generic/include/proc/task.h
r38aaacc2 rf4f866c 56 56 #include <ipc/kbox.h> 57 57 #include <mm/as.h> 58 59 #define TASK_NAME_BUFLEN 20 58 #include <sysinfo/abi.h> 60 59 61 60 struct thread; … … 81 80 task_id_t taskid; 82 81 /** Task security context. */ 83 context_id_t context; 82 context_id_t context; 84 83 85 84 /** Number of references (i.e. threads). */ … … 89 88 90 89 /** Task capabilities. */ 91 cap_t capabilities; 90 cap_t capabilities; 92 91 93 92 /* IPC stuff */ 94 93 answerbox_t answerbox; /**< Communication endpoint */ 95 94 phone_t phones[IPC_MAX_PHONES]; 95 stats_ipc_t ipc_info; /**< IPC statistics */ 96 96 /** 97 97 * Active asynchronous messages. It is used for limiting uspace to … … 119 119 mutex_t futexes_lock; 120 120 /** B+tree of futexes referenced by this task. */ 121 btree_t futexes; 121 btree_t futexes; 122 122 123 123 /** Accumulated accounting. */ 124 uint64_t cycles; 124 uint64_t ucycles; 125 uint64_t kcycles; 125 126 } task_t; 126 127 … … 134 135 extern task_t *task_find_by_id(task_id_t id); 135 136 extern int task_kill(task_id_t id); 136 extern uint64_t task_get_accounting(task_t *t);137 extern void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles); 137 138 extern void task_print_list(void); 138 139 -
kernel/generic/include/proc/thread.h
r38aaacc2 rf4f866c 48 48 #include <proc/uarg.h> 49 49 #include <udebug/udebug.h> 50 #include <sysinfo/abi.h> 50 51 51 52 #define THREAD_STACK_SIZE STACK_SIZE … … 69 70 #define THREAD_FLAG_NOATTACH (1 << 3) 70 71 71 /** Thread states. */72 typedef enum {73 /** It is an error, if thread is found in this state. */74 Invalid,75 /** State of a thread that is currently executing on some CPU. */76 Running,77 /** Thread in this state is waiting for an event. */78 Sleeping,79 /** State of threads in a run queue. */80 Ready,81 /** Threads are in this state before they are first readied. */82 Entering,83 /** After a thread calls thread_exit(), it is put into Exiting state. */84 Exiting,85 /** Threads that were not detached but exited are Lingering. */86 Lingering87 } state_t;88 89 72 /** Thread structure. There is one per thread. */ 90 73 typedef struct thread { … … 189 172 190 173 /** Thread accounting. */ 191 uint64_t cycles; 174 uint64_t ucycles; 175 uint64_t kcycles; 192 176 /** Last sampled cycle. */ 193 177 uint64_t last_cycle; … … 252 236 extern void thread_print_list(void); 253 237 extern void thread_destroy(thread_t *); 254 extern void thread_update_accounting(void); 238 extern thread_t *thread_find_by_id(thread_id_t); 239 extern void thread_update_accounting(bool); 255 240 extern bool thread_exists(thread_t *); 256 241 -
kernel/generic/include/str.h
r38aaacc2 rf4f866c 89 89 extern void wstr_to_str(char *dest, size_t size, const wchar_t *src); 90 90 91 extern char *str_dup(const char *src); 92 extern char *str_ndup(const char *src, size_t n); 93 91 94 extern char *str_chr(const char *str, wchar_t ch); 92 95 … … 94 97 extern bool wstr_remove(wchar_t *str, size_t pos); 95 98 99 extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *); 100 101 extern void order_suffix(const uint64_t val, uint64_t *rv, char *suffix); 102 96 103 #endif 97 104 -
kernel/generic/include/syscall/syscall.h
r38aaacc2 rf4f866c 71 71 SYS_IPC_REGISTER_IRQ, 72 72 SYS_IPC_UNREGISTER_IRQ, 73 73 74 74 SYS_EVENT_SUBSCRIBE, 75 75 … … 82 82 SYS_PREEMPT_CONTROL, 83 83 84 SYS_SYSINFO_VALID, 85 SYS_SYSINFO_VALUE, 84 SYS_SYSINFO_GET_TAG, 85 SYS_SYSINFO_GET_VALUE, 86 SYS_SYSINFO_GET_DATA_SIZE, 87 SYS_SYSINFO_GET_DATA, 86 88 87 89 SYS_DEBUG_ENABLE_CONSOLE, 88 90 SYS_DEBUG_DISABLE_CONSOLE, 91 89 92 SYS_IPC_CONNECT_KBOX, 90 93 SYSCALL_END -
kernel/generic/include/sysinfo/stats.h
r38aaacc2 rf4f866c 1 1 /* 2 * Copyright (c) 20 05 Jakub Vana2 * Copyright (c) 2010 Martin Decky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 #include <print.h> 30 #include <debug.h> 29 /** @addtogroup generic 30 * @{ 31 */ 32 /** @file 33 */ 31 34 32 #i nclude <test.h>33 # include <sysinfo/sysinfo.h>35 #ifndef KERN_STATS_H_ 36 #define KERN_STATS_H_ 34 37 35 const char *test_sysinfo1(void) 36 { 37 if (!test_quiet) 38 sysinfo_dump(NULL, 0); 39 return NULL; 40 } 38 extern void kload(void *arg); 39 extern void stats_init(void); 40 41 #endif 42 43 /** @} 44 */ -
kernel/generic/include/sysinfo/sysinfo.h
r38aaacc2 rf4f866c 39 39 #include <str.h> 40 40 41 /** Framebuffer info exported flags */ 41 42 extern bool fb_exported; 42 43 43 typedef union sysinfo_item_val { 44 unative_t val; 45 void *fn; 44 /** Item value type 45 * 46 */ 47 typedef enum { 48 SYSINFO_VAL_UNDEFINED = 0, /**< Undefined value */ 49 SYSINFO_VAL_VAL = 1, /**< Constant numeric value */ 50 SYSINFO_VAL_DATA = 2, /**< Constant binary data */ 51 SYSINFO_VAL_FUNCTION_VAL = 3, /**< Generated numeric value */ 52 SYSINFO_VAL_FUNCTION_DATA = 4 /**< Generated binary data */ 53 } sysinfo_item_val_type_t; 54 55 /** Subtree type 56 * 57 */ 58 typedef enum { 59 SYSINFO_SUBTREE_NONE = 0, /**< No subtree (leaf item) */ 60 SYSINFO_SUBTREE_TABLE = 1, /**< Fixed subtree */ 61 SYSINFO_SUBTREE_FUNCTION = 2 /**< Generated subtree */ 62 } sysinfo_subtree_type_t; 63 64 struct sysinfo_item; 65 66 /** Gerated numeric value function */ 67 typedef unative_t (*sysinfo_fn_val_t)(struct sysinfo_item *); 68 69 /** Generated binary data function */ 70 typedef void *(*sysinfo_fn_data_t)(struct sysinfo_item *, size_t *, bool); 71 72 /** Sysinfo item binary data 73 * 74 */ 75 typedef struct { 76 void *data; /**< Data */ 77 size_t size; /**< Size (bytes) */ 78 } sysinfo_data_t; 79 80 /** Sysinfo item value (union) 81 * 82 */ 83 typedef union { 84 unative_t val; /**< Constant numberic value */ 85 sysinfo_fn_val_t fn_val; /**< Generated numeric value function */ 86 sysinfo_fn_data_t fn_data; /**< Generated binary data function */ 87 sysinfo_data_t data; /**< Constant binary data */ 46 88 } sysinfo_item_val_t; 47 89 90 /** Sysinfo return holder 91 * 92 * This structure is generated from the constant 93 * items or by the generating functions. Note that 94 * the validity of the data is limited by the scope 95 * of single sysinfo invocation guarded by sysinfo_lock. 96 * 97 */ 98 typedef struct { 99 sysinfo_item_val_type_t tag; /**< Return value type */ 100 union { 101 unative_t val; /**< Numberic value */ 102 sysinfo_data_t data; /**< Binary data */ 103 }; 104 } sysinfo_return_t; 105 106 /** Generated subtree function */ 107 typedef sysinfo_return_t (*sysinfo_fn_subtree_t)(const char *, bool); 108 109 /** Sysinfo subtree (union) 110 * 111 */ 112 typedef union { 113 struct sysinfo_item *table; /**< Fixed subtree (list of subitems) */ 114 sysinfo_fn_subtree_t get_data; /**< Generated subtree function */ 115 } sysinfo_subtree_t; 116 117 /** Sysinfo item 118 * 119 */ 48 120 typedef struct sysinfo_item { 49 char *name; 50 union { 51 unative_t val; 52 void *fn; 53 } val; 54 55 union { 56 struct sysinfo_item *table; 57 void *fn; 58 } subinfo; 59 60 struct sysinfo_item *next; 61 int val_type; 62 int subinfo_type; 121 char *name; /**< Item name */ 122 123 sysinfo_item_val_type_t val_type; /**< Item value type */ 124 sysinfo_item_val_t val; /**< Item value */ 125 126 sysinfo_subtree_type_t subtree_type; /**< Subtree type */ 127 sysinfo_subtree_t subtree; /**< Subtree */ 128 129 struct sysinfo_item *next; /**< Sibling item */ 63 130 } sysinfo_item_t; 64 131 65 #define SYSINFO_VAL_VAL 0 66 #define SYSINFO_VAL_FUNCTION 1 67 #define SYSINFO_VAL_UNDEFINED U_SPECIAL 132 extern void sysinfo_set_item_val(const char *, sysinfo_item_t **, unative_t); 133 extern void sysinfo_set_item_data(const char *, sysinfo_item_t **, void *, 134 size_t); 135 extern void sysinfo_set_item_fn_val(const char *, sysinfo_item_t **, 136 sysinfo_fn_val_t); 137 extern void sysinfo_set_item_fn_data(const char *, sysinfo_item_t **, 138 sysinfo_fn_data_t); 139 extern void sysinfo_set_item_undefined(const char *, sysinfo_item_t **); 68 140 69 #define SYSINFO_SUBINFO_NONE 0 70 #define SYSINFO_SUBINFO_TABLE 1 71 #define SYSINFO_SUBINFO_FUNCTION 2 141 extern void sysinfo_set_subtree_fn(const char *, sysinfo_item_t **, 142 sysinfo_fn_subtree_t); 72 143 73 typedef unative_t (*sysinfo_val_fn_t)(sysinfo_item_t *root);74 typedef unative_t (*sysinfo_subinfo_fn_t)(const char *subname);144 extern void sysinfo_init(void); 145 extern void sysinfo_dump(sysinfo_item_t *); 75 146 76 typedef struct sysinfo_rettype { 77 unative_t val; 78 unative_t valid; 79 } sysinfo_rettype_t; 80 81 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val); 82 void sysinfo_dump(sysinfo_item_t **root, int depth); 83 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn); 84 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root); 85 86 sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root); 87 88 unative_t sys_sysinfo_valid(unative_t ptr, unative_t len); 89 unative_t sys_sysinfo_value(unative_t ptr, unative_t len); 147 extern unative_t sys_sysinfo_get_tag(void *, size_t); 148 extern unative_t sys_sysinfo_get_value(void *, size_t, void *); 149 extern unative_t sys_sysinfo_get_data_size(void *, size_t, void *); 150 extern unative_t sys_sysinfo_get_data(void *, size_t, void *, size_t); 90 151 91 152 #endif -
kernel/generic/include/time/clock.h
r38aaacc2 rf4f866c 38 38 #include <typedefs.h> 39 39 40 #define HZ 40 #define HZ 100 41 41 42 42 /** Uptime structure */ -
kernel/generic/src/console/cmd.c
r38aaacc2 rf4f866c 66 66 #include <ipc/irq.h> 67 67 #include <ipc/event.h> 68 #include <sysinfo/sysinfo.h> 68 69 #include <symtab.h> 69 70 #include <errno.h> … … 387 388 }; 388 389 390 static int cmd_sysinfo(cmd_arg_t *argv); 391 static cmd_info_t sysinfo_info = { 392 .name = "sysinfo", 393 .description = "Dump sysinfo.", 394 .func = cmd_sysinfo, 395 .argc = 0 396 }; 397 389 398 /* Data and methods for 'zones' command */ 390 399 static int cmd_zones(cmd_arg_t *argv); … … 475 484 &set4_info, 476 485 &slabs_info, 486 &sysinfo_info, 477 487 &symaddr_info, 478 488 &sched_info, … … 868 878 } 869 879 880 /** Command for dumping sysinfo 881 * 882 * @param argv Ignores 883 * 884 * @return Always 1 885 */ 886 int cmd_sysinfo(cmd_arg_t * argv) 887 { 888 sysinfo_dump(NULL); 889 return 1; 890 } 891 870 892 871 893 /** Command for listings Thread information … … 913 935 int cmd_zones(cmd_arg_t * argv) 914 936 { 915 zone _print_list();937 zones_print_list(); 916 938 return 1; 917 939 } … … 1027 1049 ipl_t ipl = interrupts_disable(); 1028 1050 spinlock_lock(&TASK->lock); 1029 uint64_t t0 = task_get_accounting(TASK); 1051 uint64_t ucycles0, kcycles0; 1052 task_get_accounting(TASK, &ucycles0, &kcycles0); 1030 1053 spinlock_unlock(&TASK->lock); 1031 1054 interrupts_restore(ipl); … … 1036 1059 1037 1060 /* Update and read thread accounting */ 1061 uint64_t ucycles1, kcycles1; 1038 1062 ipl = interrupts_disable(); 1039 1063 spinlock_lock(&TASK->lock); 1040 uint64_t dt = task_get_accounting(TASK) - t0;1064 task_get_accounting(TASK, &ucycles1, &kcycles1); 1041 1065 spinlock_unlock(&TASK->lock); 1042 1066 interrupts_restore(ipl); 1043 1067 1044 uint64_t cycles; 1045 char suffix; 1046 order(dt, &cycles, &suffix); 1047 1048 printf("Time: %" PRIu64 "%c cycles\n", cycles, suffix); 1068 uint64_t ucycles, kcycles; 1069 char usuffix, ksuffix; 1070 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix); 1071 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix); 1072 1073 printf("Time: %" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles\n", 1074 ucycles, usuffix, kcycles, ksuffix); 1049 1075 1050 1076 if (ret == NULL) { … … 1061 1087 uint32_t i; 1062 1088 bool ret = true; 1063 uint64_t cycles;1064 char suffix;1089 uint64_t ucycles, kcycles; 1090 char usuffix, ksuffix; 1065 1091 1066 1092 if (cnt < 1) … … 1080 1106 ipl_t ipl = interrupts_disable(); 1081 1107 spinlock_lock(&TASK->lock); 1082 uint64_t t0 = task_get_accounting(TASK); 1108 uint64_t ucycles0, kcycles0; 1109 task_get_accounting(TASK, &ucycles0, &kcycles0); 1083 1110 spinlock_unlock(&TASK->lock); 1084 1111 interrupts_restore(ipl); … … 1091 1118 ipl = interrupts_disable(); 1092 1119 spinlock_lock(&TASK->lock); 1093 uint64_t dt = task_get_accounting(TASK) - t0; 1120 uint64_t ucycles1, kcycles1; 1121 task_get_accounting(TASK, &ucycles1, &kcycles1); 1094 1122 spinlock_unlock(&TASK->lock); 1095 1123 interrupts_restore(ipl); 1096 1124 1097 1125 if (ret != NULL) { 1098 1126 printf("%s\n", ret); … … 1101 1129 } 1102 1130 1103 data[i] = dt; 1104 order(dt, &cycles, &suffix); 1105 printf("OK (%" PRIu64 "%c cycles)\n", cycles, suffix); 1131 data[i] = ucycles1 - ucycles0 + kcycles1 - kcycles0; 1132 order_suffix(ucycles1 - ucycles0, &ucycles, &usuffix); 1133 order_suffix(kcycles1 - kcycles0, &kcycles, &ksuffix); 1134 printf("OK (%" PRIu64 "%c user cycles, %" PRIu64 "%c kernel cycles)\n", 1135 ucycles, usuffix, kcycles, ksuffix); 1106 1136 } 1107 1137 … … 1115 1145 } 1116 1146 1117 order (sum / (uint64_t) cnt, &cycles, &suffix);1118 printf("Average\t\t%" PRIu64 "%c\n", cycles,suffix);1147 order_suffix(sum / (uint64_t) cnt, &ucycles, &usuffix); 1148 printf("Average\t\t%" PRIu64 "%c\n", ucycles, usuffix); 1119 1149 } 1120 1150 -
kernel/generic/src/cpu/cpu.c
r38aaacc2 rf4f866c 48 48 #include <adt/list.h> 49 49 #include <print.h> 50 #include <sysinfo/sysinfo.h> 50 51 51 52 cpu_t *cpus; -
kernel/generic/src/interrupt/interrupt.c
r38aaacc2 rf4f866c 51 51 #include <print.h> 52 52 #include <symtab.h> 53 #include <proc/thread.h> 53 54 54 55 static struct { … … 91 92 ASSERT(n < IVT_ITEMS); 92 93 94 /* Account user cycles */ 95 if (THREAD) 96 thread_update_accounting(true); 97 93 98 #ifdef CONFIG_UDEBUG 94 99 if (THREAD) THREAD->udebug.uspace_state = istate; … … 104 109 if (THREAD && THREAD->interrupted && istate_from_uspace(istate)) 105 110 thread_exit(); 111 112 if (THREAD) 113 thread_update_accounting(false); 106 114 } 107 115 -
kernel/generic/src/ipc/ipc.c
r38aaacc2 rf4f866c 219 219 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 220 220 221 /* Count sent answer */ 222 spinlock_lock(&TASK->lock); 223 TASK->ipc_info.answer_sent++; 224 spinlock_unlock(&TASK->lock); 225 221 226 call->flags |= IPC_CALL_ANSWERED; 222 227 … … 276 281 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 277 282 { 283 /* Count sent ipc call */ 284 spinlock_lock(&TASK->lock); 285 TASK->ipc_info.call_sent++; 286 spinlock_unlock(&TASK->lock); 287 278 288 if (!(call->flags & IPC_CALL_FORWARDED)) { 279 289 atomic_inc(&phone->active_calls); … … 376 386 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode) 377 387 { 388 /* Count forwarded calls */ 389 spinlock_lock(&TASK->lock); 390 TASK->ipc_info.forwarded++; 391 spinlock_unlock(&TASK->lock); 392 378 393 spinlock_lock(&oldbox->lock); 379 394 list_remove(&call->link); … … 416 431 spinlock_lock(&box->lock); 417 432 if (!list_empty(&box->irq_notifs)) { 433 434 /* Count recieved IRQ notification */ 435 spinlock_lock(&TASK->lock); 436 TASK->ipc_info.irq_notif_recieved++; 437 spinlock_unlock(&TASK->lock); 438 418 439 ipl = interrupts_disable(); 419 440 spinlock_lock(&box->irq_lock); … … 425 446 interrupts_restore(ipl); 426 447 } else if (!list_empty(&box->answers)) { 448 /* Count recieved answer */ 449 spinlock_lock(&TASK->lock); 450 TASK->ipc_info.answer_recieved++; 451 spinlock_unlock(&TASK->lock); 452 427 453 /* Handle asynchronous answers */ 428 454 request = list_get_instance(box->answers.next, call_t, link); … … 430 456 atomic_dec(&request->data.phone->active_calls); 431 457 } else if (!list_empty(&box->calls)) { 458 /* Count recieved call */ 459 spinlock_lock(&TASK->lock); 460 TASK->ipc_info.call_recieved++; 461 spinlock_unlock(&TASK->lock); 462 432 463 /* Handle requests */ 433 464 request = list_get_instance(box->calls.next, call_t, link); -
kernel/generic/src/ipc/sysipc.c
r38aaacc2 rf4f866c 58 58 #define DATA_XFER_LIMIT (64 * 1024) 59 59 60 #define GET_CHECK_PHONE(phone, phoneid, err) \ 61 { \ 62 if (phoneid > IPC_MAX_PHONES) { \ 63 err \ 64 } \ 65 phone = &TASK->phones[phoneid]; \ 60 /** Get phone from the current task by ID. 61 * 62 * @param phoneid Phone ID. 63 * @param phone Place to store pointer to phone. 64 * @return EOK on success, EINVAL if ID is invalid. 65 */ 66 static int phone_get(unative_t phoneid, phone_t **phone) 67 { 68 if (phoneid >= IPC_MAX_PHONES) 69 return EINVAL; 70 71 *phone = &TASK->phones[phoneid]; 72 return EOK; 66 73 } 67 74 … … 374 381 case IPC_M_CONNECTION_CLONE: { 375 382 phone_t *cloned_phone; 376 GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data), 377 return ENOENT;); 383 384 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 385 return ENOENT; 378 386 phones_lock(cloned_phone, phone); 387 379 388 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 380 389 phone->state != IPC_PHONE_CONNECTED) { … … 534 543 int res; 535 544 int rc; 536 537 GET_CHECK_PHONE(phone, phoneid, return ENOENT;); 545 546 if (phone_get(phoneid, &phone) != EOK) 547 return ENOENT; 538 548 539 549 call = ipc_call_alloc(0); … … 591 601 int rc; 592 602 593 GET_CHECK_PHONE(phone, phoneid, return ENOENT;); 603 if (phone_get(phoneid, &phone) != EOK) 604 return ENOENT; 594 605 595 606 call = ipc_call_alloc(0); … … 666 677 return IPC_CALLRET_TEMPORARY; 667 678 668 GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;); 679 if (phone_get(phoneid, &phone) != EOK) 680 return IPC_CALLRET_FATAL; 669 681 670 682 call = ipc_call_alloc(0); … … 705 717 return IPC_CALLRET_TEMPORARY; 706 718 707 GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;); 719 if (phone_get(phoneid, &phone) != EOK) 720 return IPC_CALLRET_FATAL; 708 721 709 722 call = ipc_call_alloc(0); … … 755 768 call->flags |= IPC_CALL_FORWARDED; 756 769 757 GET_CHECK_PHONE(phone, phoneid,{770 if (phone_get(phoneid, &phone) != EOK) { 758 771 IPC_SET_RETVAL(call->data, EFORWARD); 759 772 ipc_answer(&TASK->answerbox, call); 760 773 return ENOENT; 761 } );774 } 762 775 763 776 if (!method_is_forwardable(IPC_GET_METHOD(call->data))) { … … 956 969 * @return Return 0 on success or an error code. 957 970 */ 958 unative_t sys_ipc_hangup( int phoneid)971 unative_t sys_ipc_hangup(unative_t phoneid) 959 972 { 960 973 phone_t *phone; 961 974 962 GET_CHECK_PHONE(phone, phoneid, return ENOENT;); 975 if (phone_get(phoneid, &phone) != EOK) 976 return ENOENT; 963 977 964 978 if (ipc_phone_hangup(phone)) -
kernel/generic/src/lib/func.c
r38aaacc2 rf4f866c 123 123 } 124 124 125 126 void order(const uint64_t val, uint64_t *rv, char *suffix)127 {128 if (val > 10000000000000000000ULL) {129 *rv = val / 1000000000000000000ULL;130 *suffix = 'Z';131 } else if (val > 1000000000000000000ULL) {132 *rv = val / 1000000000000000ULL;133 *suffix = 'E';134 } else if (val > 1000000000000000ULL) {135 *rv = val / 1000000000000ULL;136 *suffix = 'T';137 } else if (val > 1000000000000ULL) {138 *rv = val / 1000000000ULL;139 *suffix = 'G';140 } else if (val > 1000000000ULL) {141 *rv = val / 1000000ULL;142 *suffix = 'M';143 } else if (val > 1000000ULL) {144 *rv = val / 1000ULL;145 *suffix = 'k';146 } else {147 *rv = val;148 *suffix = ' ';149 }150 }151 152 125 /** @} 153 126 */ -
kernel/generic/src/lib/str.c
r38aaacc2 rf4f866c 110 110 #include <align.h> 111 111 #include <debug.h> 112 #include <macros.h> 112 113 113 114 /** Byte mask consisting of lowest @n bits (out of 8) */ … … 537 538 * null-terminated and containing only complete characters. 538 539 * 539 * @param dest 540 * @param dest Destination buffer. 540 541 * @param count Size of the destination buffer (must be > 0). 541 542 * @param src Source string. 543 * 542 544 */ 543 545 void str_cpy(char *dest, size_t size, const char *src) 544 546 { 545 wchar_t ch;546 size_t src_off;547 size_t dest_off;548 549 547 /* There must be space for a null terminator in the buffer. */ 550 548 ASSERT(size > 0); 551 549 552 src_off = 0; 553 dest_off = 0; 554 550 size_t src_off = 0; 551 size_t dest_off = 0; 552 553 wchar_t ch; 555 554 while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { 556 555 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 557 556 break; 558 557 } 559 558 560 559 dest[dest_off] = '\0'; 561 560 } … … 571 570 * have to be null-terminated. 572 571 * 573 * @param dest 572 * @param dest Destination buffer. 574 573 * @param count Size of the destination buffer (must be > 0). 575 574 * @param src Source string. 576 * @param n Maximum number of bytes to read from @a src. 575 * @param n Maximum number of bytes to read from @a src. 576 * 577 577 */ 578 578 void str_ncpy(char *dest, size_t size, const char *src, size_t n) 579 579 { 580 wchar_t ch;581 size_t src_off;582 size_t dest_off;583 584 580 /* There must be space for a null terminator in the buffer. */ 585 581 ASSERT(size > 0); 586 582 587 src_off = 0; 588 dest_off = 0; 589 583 size_t src_off = 0; 584 size_t dest_off = 0; 585 586 wchar_t ch; 590 587 while ((ch = str_decode(src, &src_off, n)) != 0) { 591 588 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 592 589 break; 593 590 } 594 591 595 592 dest[dest_off] = '\0'; 593 } 594 595 /** Duplicate string. 596 * 597 * Allocate a new string and copy characters from the source 598 * string into it. The duplicate string is allocated via sleeping 599 * malloc(), thus this function can sleep in no memory conditions. 600 * 601 * The allocation cannot fail and the return value is always 602 * a valid pointer. The duplicate string is always a well-formed 603 * null-terminated UTF-8 string, but it can differ from the source 604 * string on the byte level. 605 * 606 * @param src Source string. 607 * 608 * @return Duplicate string. 609 * 610 */ 611 char *str_dup(const char *src) 612 { 613 size_t size = str_size(src) + 1; 614 char *dest = malloc(size, 0); 615 ASSERT(dest); 616 617 str_cpy(dest, size, src); 618 return dest; 619 } 620 621 /** Duplicate string with size limit. 622 * 623 * Allocate a new string and copy up to @max_size bytes from the source 624 * string into it. The duplicate string is allocated via sleeping 625 * malloc(), thus this function can sleep in no memory conditions. 626 * No more than @max_size + 1 bytes is allocated, but if the size 627 * occupied by the source string is smaller than @max_size + 1, 628 * less is allocated. 629 * 630 * The allocation cannot fail and the return value is always 631 * a valid pointer. The duplicate string is always a well-formed 632 * null-terminated UTF-8 string, but it can differ from the source 633 * string on the byte level. 634 * 635 * @param src Source string. 636 * @param n Maximum number of bytes to duplicate. 637 * 638 * @return Duplicate string. 639 * 640 */ 641 char *str_ndup(const char *src, size_t n) 642 { 643 size_t size = str_size(src); 644 if (size > n) 645 size = n; 646 647 char *dest = malloc(size + 1, 0); 648 ASSERT(dest); 649 650 str_ncpy(dest, size + 1, src, size); 651 return dest; 596 652 } 597 653 … … 705 761 } 706 762 763 /** Convert string to uint64_t (internal variant). 764 * 765 * @param nptr Pointer to string. 766 * @param endptr Pointer to the first invalid character is stored here. 767 * @param base Zero or number between 2 and 36 inclusive. 768 * @param neg Indication of unary minus is stored here. 769 * @apram result Result of the conversion. 770 * 771 * @return EOK if conversion was successful. 772 * 773 */ 774 static int str_uint(const char *nptr, char **endptr, unsigned int base, 775 bool *neg, uint64_t *result) 776 { 777 ASSERT(endptr != NULL); 778 ASSERT(neg != NULL); 779 ASSERT(result != NULL); 780 781 *neg = false; 782 const char *str = nptr; 783 784 /* Ignore leading whitespace */ 785 while (isspace(*str)) 786 str++; 787 788 if (*str == '-') { 789 *neg = true; 790 str++; 791 } else if (*str == '+') 792 str++; 793 794 if (base == 0) { 795 /* Decode base if not specified */ 796 base = 10; 797 798 if (*str == '0') { 799 base = 8; 800 str++; 801 802 switch (*str) { 803 case 'b': 804 case 'B': 805 base = 2; 806 str++; 807 break; 808 case 'o': 809 case 'O': 810 base = 8; 811 str++; 812 break; 813 case 'd': 814 case 'D': 815 case 't': 816 case 'T': 817 base = 10; 818 str++; 819 break; 820 case 'x': 821 case 'X': 822 base = 16; 823 str++; 824 break; 825 } 826 } 827 } else { 828 /* Check base range */ 829 if ((base < 2) || (base > 36)) { 830 *endptr = (char *) str; 831 return EINVAL; 832 } 833 } 834 835 *result = 0; 836 const char *startstr = str; 837 838 while (*str != 0) { 839 unsigned int digit; 840 841 if ((*str >= 'a') && (*str <= 'z')) 842 digit = *str - 'a' + 10; 843 else if ((*str >= 'A') && (*str <= 'Z')) 844 digit = *str - 'A' + 10; 845 else if ((*str >= '0') && (*str <= '9')) 846 digit = *str - '0'; 847 else 848 break; 849 850 if (digit >= base) 851 break; 852 853 uint64_t prev = *result; 854 *result = (*result) * base + digit; 855 856 if (*result < prev) { 857 /* Overflow */ 858 *endptr = (char *) str; 859 return EOVERFLOW; 860 } 861 862 str++; 863 } 864 865 if (str == startstr) { 866 /* 867 * No digits were decoded => first invalid character is 868 * the first character of the string. 869 */ 870 str = nptr; 871 } 872 873 *endptr = (char *) str; 874 875 if (str == nptr) 876 return EINVAL; 877 878 return EOK; 879 } 880 881 /** Convert string to uint64_t. 882 * 883 * @param nptr Pointer to string. 884 * @param endptr If not NULL, pointer to the first invalid character 885 * is stored here. 886 * @param base Zero or number between 2 and 36 inclusive. 887 * @param strict Do not allow any trailing characters. 888 * @apram result Result of the conversion. 889 * 890 * @return EOK if conversion was successful. 891 * 892 */ 893 int str_uint64(const char *nptr, char **endptr, unsigned int base, 894 bool strict, uint64_t *result) 895 { 896 ASSERT(result != NULL); 897 898 bool neg; 899 char *lendptr; 900 int ret = str_uint(nptr, &lendptr, base, &neg, result); 901 902 if (endptr != NULL) 903 *endptr = (char *) lendptr; 904 905 if (ret != EOK) 906 return ret; 907 908 /* Do not allow negative values */ 909 if (neg) 910 return EINVAL; 911 912 /* Check whether we are at the end of 913 the string in strict mode */ 914 if ((strict) && (*lendptr != 0)) 915 return EINVAL; 916 917 return EOK; 918 } 919 920 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix) 921 { 922 if (val > 10000000000000000000ULL) { 923 *rv = val / 1000000000000000000ULL; 924 *suffix = 'Z'; 925 } else if (val > 1000000000000000000ULL) { 926 *rv = val / 1000000000000000ULL; 927 *suffix = 'E'; 928 } else if (val > 1000000000000000ULL) { 929 *rv = val / 1000000000000ULL; 930 *suffix = 'T'; 931 } else if (val > 1000000000000ULL) { 932 *rv = val / 1000000000ULL; 933 *suffix = 'G'; 934 } else if (val > 1000000000ULL) { 935 *rv = val / 1000000ULL; 936 *suffix = 'M'; 937 } else if (val > 1000000ULL) { 938 *rv = val / 1000ULL; 939 *suffix = 'k'; 940 } else { 941 *rv = val; 942 *suffix = ' '; 943 } 944 } 945 707 946 /** @} 708 947 */ -
kernel/generic/src/main/kinit.c
r38aaacc2 rf4f866c 67 67 #include <debug.h> 68 68 #include <str.h> 69 #include <sysinfo/stats.h> 69 70 70 71 #ifdef CONFIG_SMP … … 122 123 } else 123 124 panic("Unable to create kmp thread."); 125 124 126 thread_join(thread); 125 127 thread_detach(thread); … … 149 151 */ 150 152 arch_post_smp_init(); 153 154 /* Start thread computing system load */ 155 thread = thread_create(kload, NULL, TASK, 0, "kload", false); 156 if (thread != NULL) 157 thread_ready(thread); 158 else 159 printf("Unable to create kload thread\n"); 151 160 152 161 #ifdef CONFIG_KCONSOLE -
kernel/generic/src/main/main.c
r38aaacc2 rf4f866c 84 84 #include <main/main.h> 85 85 #include <ipc/event.h> 86 #include <sysinfo/sysinfo.h> 87 #include <sysinfo/stats.h> 86 88 87 89 /** Global configuration structure. */ … … 209 211 /* Initialize at least 1 memory segment big enough for slab to work. */ 210 212 LOG_EXEC(slab_cache_init()); 213 LOG_EXEC(sysinfo_init()); 211 214 LOG_EXEC(btree_init()); 212 215 LOG_EXEC(as_init()); … … 223 226 224 227 printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n", 225 config.cpu_count, SIZE2MB(zone _total_size()));226 228 config.cpu_count, SIZE2MB(zones_total_size())); 229 227 230 LOG_EXEC(cpu_init()); 228 231 … … 247 250 LOG_EXEC(event_init()); 248 251 LOG_EXEC(klog_init()); 252 LOG_EXEC(stats_init()); 249 253 250 254 /* -
kernel/generic/src/main/version.c
r38aaacc2 rf4f866c 59 59 { 60 60 printf("%s, release %s (%s)%s\nBuilt%s for %s\n%s\n", 61 61 project, release, name, revision, timestamp, arch, copyright); 62 62 } 63 63 -
kernel/generic/src/mm/frame.c
r38aaacc2 rf4f866c 1202 1202 1203 1203 /** Return total size of all zones. */ 1204 uint64_t zone _total_size(void)1204 uint64_t zones_total_size(void) 1205 1205 { 1206 1206 ipl_t ipl = interrupts_disable(); … … 1218 1218 } 1219 1219 1220 void zones_stats(uint64_t *total, uint64_t *unavail, uint64_t *busy, 1221 uint64_t *free) 1222 { 1223 ASSERT(total != NULL); 1224 ASSERT(unavail != NULL); 1225 ASSERT(busy != NULL); 1226 ASSERT(free != NULL); 1227 1228 ipl_t ipl = interrupts_disable(); 1229 spinlock_lock(&zones.lock); 1230 1231 *total = 0; 1232 *unavail = 0; 1233 *busy = 0; 1234 *free = 0; 1235 1236 size_t i; 1237 for (i = 0; i < zones.count; i++) { 1238 *total += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1239 1240 if (zone_flags_available(zones.info[i].flags)) { 1241 *busy += (uint64_t) FRAMES2SIZE(zones.info[i].busy_count); 1242 *free += (uint64_t) FRAMES2SIZE(zones.info[i].free_count); 1243 } else 1244 *unavail += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1245 } 1246 1247 spinlock_unlock(&zones.lock); 1248 interrupts_restore(ipl); 1249 } 1250 1220 1251 /** Prints list of zones. */ 1221 void zone _print_list(void)1252 void zones_print_list(void) 1222 1253 { 1223 1254 #ifdef __32_BITS__ -
kernel/generic/src/printf/printf.c
r38aaacc2 rf4f866c 34 34 35 35 #include <print.h> 36 #include <stdarg.h> 36 37 37 38 int printf(const char *fmt, ...) -
kernel/generic/src/printf/printf_core.c
r38aaacc2 rf4f866c 46 46 /** show prefixes 0x or 0 */ 47 47 #define __PRINTF_FLAG_PREFIX 0x00000001 48 48 49 /** signed / unsigned number */ 49 50 #define __PRINTF_FLAG_SIGNED 0x00000002 51 50 52 /** print leading zeroes */ 51 53 #define __PRINTF_FLAG_ZEROPADDED 0x00000004 54 52 55 /** align to left */ 53 56 #define __PRINTF_FLAG_LEFTALIGNED 0x00000010 57 54 58 /** always show + sign */ 55 59 #define __PRINTF_FLAG_SHOWPLUS 0x00000020 60 56 61 /** print space instead of plus */ 57 62 #define __PRINTF_FLAG_SPACESIGN 0x00000040 63 58 64 /** show big characters */ 59 65 #define __PRINTF_FLAG_BIGCHARS 0x00000080 66 60 67 /** number has - sign */ 61 68 #define __PRINTF_FLAG_NEGATIVE 0x00000100 … … 79 86 } qualifier_t; 80 87 81 static c har nullstr[]= "(NULL)";82 static c har digits_small[]= "0123456789abcdef";83 static c har digits_big[]= "0123456789ABCDEF";84 static c har invalch = U_SPECIAL;88 static const char *nullstr = "(NULL)"; 89 static const char *digits_small = "0123456789abcdef"; 90 static const char *digits_big = "0123456789ABCDEF"; 91 static const char invalch = U_SPECIAL; 85 92 86 93 /** Print one or more characters without adding newline. … … 351 358 uint32_t flags, printf_spec_t *ps) 352 359 { 353 c har *digits;360 const char *digits; 354 361 if (flags & __PRINTF_FLAG_BIGCHARS) 355 362 digits = digits_big; -
kernel/generic/src/proc/scheduler.c
r38aaacc2 rf4f866c 202 202 */ 203 203 204 spinlock_lock(&CPU->lock); 205 CPU->idle = true; 206 spinlock_unlock(&CPU->lock); 204 207 cpu_sleep(); 205 208 goto loop; … … 313 316 spinlock_lock(&THREAD->lock); 314 317 315 /* Update thread accounting */316 THREAD-> cycles += get_cycle() - THREAD->last_cycle;318 /* Update thread kernel accounting */ 319 THREAD->kcycles += get_cycle() - THREAD->last_cycle; 317 320 318 321 #ifndef CONFIG_FPU_LAZY -
kernel/generic/src/proc/task.c
r38aaacc2 rf4f866c 33 33 /** 34 34 * @file 35 * @brief 35 * @brief Task management. 36 36 */ 37 37 … … 66 66 * The task is guaranteed to exist after it was found in the tasks_tree as 67 67 * long as: 68 * 68 69 * @li the tasks_lock is held, 69 70 * @li the task's lock is held when task's lock is acquired before releasing … … 99 100 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node); 100 101 unsigned *cnt = (unsigned *) arg; 101 102 102 103 if (t != TASK) { 103 104 (*cnt)++; … … 107 108 task_kill_internal(t); 108 109 } 109 110 return true; /* continue the walk */ 110 111 /* Continue the walk */ 112 return true; 111 113 } 112 114 … … 115 117 { 116 118 unsigned tasks_left; 117 119 118 120 do { /* Repeat until there are any tasks except TASK */ 119 121 /* Messing with task structures, avoid deadlock */ … … 138 140 task_t *ta = obj; 139 141 int i; 140 142 141 143 atomic_set(&ta->refcount, 0); 142 144 atomic_set(&ta->lifecount, 0); 143 145 atomic_set(&ta->active_calls, 0); 144 146 145 147 spinlock_initialize(&ta->lock, "task_ta_lock"); 146 148 mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE); 147 149 148 150 list_initialize(&ta->th_head); 149 151 list_initialize(&ta->sync_box_head); 150 152 151 153 ipc_answerbox_init(&ta->answerbox, ta); 152 154 for (i = 0; i < IPC_MAX_PHONES; i++) 153 155 ipc_phone_init(&ta->phones[i]); 154 156 155 157 #ifdef CONFIG_UDEBUG 156 158 /* Init kbox stuff */ … … 159 161 mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE); 160 162 #endif 161 163 162 164 return 0; 163 165 } … … 165 167 /** Create new task with no threads. 166 168 * 167 * @param as 168 * @param name 169 * 170 * @return 169 * @param as Task's address space. 170 * @param name Symbolic name (a copy is made). 171 * 172 * @return New task's structure. 171 173 * 172 174 */ … … 181 183 memcpy(ta->name, name, TASK_NAME_BUFLEN); 182 184 ta->name[TASK_NAME_BUFLEN - 1] = 0; 183 185 184 186 ta->context = CONTEXT; 185 187 ta->capabilities = 0; 186 ta->cycles = 0; 188 ta->ucycles = 0; 189 ta->kcycles = 0; 190 191 ta->ipc_info.call_sent = 0; 192 ta->ipc_info.call_recieved = 0; 193 ta->ipc_info.answer_sent = 0; 194 ta->ipc_info.answer_recieved = 0; 195 ta->ipc_info.irq_notif_recieved = 0; 196 ta->ipc_info.forwarded = 0; 187 197 188 198 #ifdef CONFIG_UDEBUG 189 199 /* Init debugging stuff */ 190 200 udebug_task_init(&ta->udebug); 191 201 192 202 /* Init kbox stuff */ 193 203 ta->kb.finished = false; 194 204 #endif 195 205 196 206 if ((ipc_phone_0) && 197 207 (context_check(ipc_phone_0->task->context, ta->context))) 198 208 ipc_phone_connect(&ta->phones[0], ipc_phone_0); 199 209 200 210 btree_create(&ta->futexes); 201 211 … … 215 225 /** Destroy task. 216 226 * 217 * @param t Task to be destroyed. 227 * @param t Task to be destroyed. 228 * 218 229 */ 219 230 void task_destroy(task_t *t) … … 225 236 avltree_delete(&tasks_tree, &t->tasks_tree_node); 226 237 spinlock_unlock(&tasks_lock); 227 238 228 239 /* 229 240 * Perform architecture specific task destruction. 230 241 */ 231 242 task_destroy_arch(t); 232 243 233 244 /* 234 245 * Free up dynamically allocated state. 235 246 */ 236 247 btree_destroy(&t->futexes); 237 248 238 249 /* 239 250 * Drop our reference to the address space. … … 248 259 /** Syscall for reading task ID from userspace. 249 260 * 250 * @param uspace_task_id userspace address of 8-byte buffer 251 * where to store current task ID. 252 * 253 * @return Zero on success or an error code from @ref errno.h. 261 * @param uspace_task_id Userspace address of 8-byte buffer 262 * where to store current task ID. 263 * 264 * @return Zero on success or an error code from @ref errno.h. 265 * 254 266 */ 255 267 unative_t sys_task_get_id(task_id_t *uspace_task_id) … … 267 279 * The name simplifies identifying the task in the task list. 268 280 * 269 * @param name 270 * 281 * @param name The new name for the task. (typically the same 282 * as the command used to execute it). 271 283 * 272 284 * @return 0 on success or an error code from @ref errno.h. 285 * 273 286 */ 274 287 unative_t sys_task_set_name(const char *uspace_name, size_t name_len) … … 276 289 int rc; 277 290 char namebuf[TASK_NAME_BUFLEN]; 278 291 279 292 /* Cap length of name and copy it from userspace. */ 280 293 281 294 if (name_len > TASK_NAME_BUFLEN - 1) 282 295 name_len = TASK_NAME_BUFLEN - 1; 283 296 284 297 rc = copy_from_uspace(namebuf, uspace_name, name_len); 285 298 if (rc != 0) 286 299 return (unative_t) rc; 287 300 288 301 namebuf[name_len] = '\0'; 289 302 str_cpy(TASK->name, TASK_NAME_BUFLEN, namebuf); 290 303 291 304 return EOK; 292 305 } … … 297 310 * interrupts must be disabled. 298 311 * 299 * @param id Task ID. 300 * 301 * @return Task structure address or NULL if there is no such task 302 * ID. 303 */ 304 task_t *task_find_by_id(task_id_t id) { avltree_node_t *node; 305 306 node = avltree_search(&tasks_tree, (avltree_key_t) id); 307 312 * @param id Task ID. 313 * 314 * @return Task structure address or NULL if there is no such task ID. 315 * 316 */ 317 task_t *task_find_by_id(task_id_t id) 318 { 319 avltree_node_t *node = 320 avltree_search(&tasks_tree, (avltree_key_t) id); 321 308 322 if (node) 309 323 return avltree_get_instance(node, task_t, tasks_tree_node); 324 310 325 return NULL; 311 326 } … … 316 331 * already disabled. 317 332 * 318 * @param t Pointer to thread. 319 * 320 * @return Number of cycles used by the task and all its threads 321 * so far. 322 */ 323 uint64_t task_get_accounting(task_t *t) 324 { 325 /* Accumulated value of task */ 326 uint64_t ret = t->cycles; 333 * @param t Pointer to thread. 334 * @param ucycles Out pointer to sum of all user cycles. 335 * @param kcycles Out pointer to sum of all kernel cycles. 336 * 337 */ 338 void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles) 339 { 340 /* Accumulated values of task */ 341 uint64_t uret = t->ucycles; 342 uint64_t kret = t->kcycles; 327 343 328 344 /* Current values of threads */ … … 336 352 if (thr == THREAD) { 337 353 /* Update accounting of current thread */ 338 thread_update_accounting( );354 thread_update_accounting(false); 339 355 } 340 ret += thr->cycles; 356 uret += thr->ucycles; 357 kret += thr->kcycles; 341 358 } 342 359 spinlock_unlock(&thr->lock); 343 360 } 344 361 345 return ret; 362 *ucycles = uret; 363 *kcycles = kret; 346 364 } 347 365 … … 349 367 { 350 368 link_t *cur; 351 369 352 370 /* 353 371 * Interrupt all threads. … … 377 395 * It signals all the task's threads to bail it out. 378 396 * 379 * @param id ID of the task to be killed. 380 * 381 * @return Zero on success or an error code from errno.h. 397 * @param id ID of the task to be killed. 398 * 399 * @return Zero on success or an error code from errno.h. 400 * 382 401 */ 383 402 int task_kill(task_id_t id) … … 406 425 task_t *t = avltree_get_instance(node, task_t, tasks_tree_node); 407 426 int j; 408 427 409 428 spinlock_lock(&t->lock); 410 411 uint64_t cycles; 412 char suffix; 413 order(task_get_accounting(t), &cycles, &suffix); 414 429 430 uint64_t ucycles; 431 uint64_t kcycles; 432 char usuffix, ksuffix; 433 task_get_accounting(t, &ucycles, &kcycles); 434 order_suffix(ucycles, &ucycles, &usuffix); 435 order_suffix(kcycles, &kcycles, &ksuffix); 436 415 437 #ifdef __32_BITS__ 416 printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 417 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, 418 suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); 419 #endif 420 438 printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 "%c %9" 439 PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, 440 ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount), 441 atomic_get(&t->active_calls)); 442 #endif 443 421 444 #ifdef __64_BITS__ 422 printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 423 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, 424 suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); 425 #endif 426 445 printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 "%c %9" 446 PRIu64 "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, 447 ucycles, usuffix, kcycles, ksuffix, atomic_get(&t->refcount), 448 atomic_get(&t->active_calls)); 449 #endif 450 427 451 for (j = 0; j < IPC_MAX_PHONES; j++) { 428 452 if (t->phones[j].callee) … … 430 454 } 431 455 printf("\n"); 432 456 433 457 spinlock_unlock(&t->lock); 434 458 return true; … … 443 467 ipl = interrupts_disable(); 444 468 spinlock_lock(&tasks_lock); 445 446 #ifdef __32_BITS__ 447 printf("taskid name ctx address as 448 " cyclesthreads calls callee\n");449 printf("------ ------------ --- ---------- ---------- 450 " ---------- ------- ------ ------>\n");451 #endif 452 469 470 #ifdef __32_BITS__ 471 printf("taskid name ctx address as " 472 " ucycles kcycles threads calls callee\n"); 473 printf("------ ------------ --- ---------- ----------" 474 " ---------- ---------- ------- ------ ------>\n"); 475 #endif 476 453 477 #ifdef __64_BITS__ 454 printf("taskid name ctx address as 455 " cyclesthreads calls callee\n");456 printf("------ ------------ --- ------------------ ------------------ 457 " ---------- ------- ------ ------>\n");458 #endif 459 478 printf("taskid name ctx address as " 479 " ucycles kcycles threads calls callee\n"); 480 printf("------ ------------ --- ------------------ ------------------" 481 " ---------- ---------- ---------- ------- ------ ------>\n"); 482 #endif 483 460 484 avltree_walk(&tasks_tree, task_print_walker, NULL); 461 485 462 486 spinlock_unlock(&tasks_lock); 463 487 interrupts_restore(ipl); -
kernel/generic/src/proc/thread.c
r38aaacc2 rf4f866c 50 50 #include <synch/rwlock.h> 51 51 #include <cpu.h> 52 #include < func.h>52 #include <str.h> 53 53 #include <context.h> 54 54 #include <adt/avl.h> … … 84 84 "Exiting", 85 85 "Lingering" 86 }; 86 }; 87 88 typedef struct { 89 thread_id_t thread_id; 90 thread_t *thread; 91 } thread_iterator_t; 87 92 88 93 /** Lock protecting the threads_tree AVL tree. … … 132 137 spinlock_lock(&THREAD->lock); 133 138 if (!THREAD->uncounted) { 134 thread_update_accounting(); 135 uint64_t cycles = THREAD->cycles; 136 THREAD->cycles = 0; 139 thread_update_accounting(true); 140 uint64_t ucycles = THREAD->ucycles; 141 THREAD->ucycles = 0; 142 uint64_t kcycles = THREAD->kcycles; 143 THREAD->kcycles = 0; 144 137 145 spinlock_unlock(&THREAD->lock); 138 146 139 147 spinlock_lock(&TASK->lock); 140 TASK->cycles += cycles; 148 TASK->ucycles += ucycles; 149 TASK->kcycles += kcycles; 141 150 spinlock_unlock(&TASK->lock); 142 151 } else … … 323 332 t->thread_arg = arg; 324 333 t->ticks = -1; 325 t->cycles = 0; 334 t->ucycles = 0; 335 t->kcycles = 0; 326 336 t->uncounted = uncounted; 327 337 t->priority = -1; /* start in rq[0] */ … … 614 624 thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node); 615 625 616 uint64_t cycles; 617 char suffix; 618 order(t->cycles, &cycles, &suffix); 626 uint64_t ucycles, kcycles; 627 char usuffix, ksuffix; 628 order_suffix(t->ucycles, &ucycles, &usuffix); 629 order_suffix(t->kcycles, &kcycles, &ksuffix); 619 630 620 631 #ifdef __32_BITS__ 621 printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ", 622 t->tid, t->name, t, thread_states[t->state], t->task, 623 t->task->context, t->thread_code, t->kstack, cycles, suffix); 632 printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" 633 PRIu64 "%c %9" PRIu64 "%c ", t->tid, t->name, t, 634 thread_states[t->state], t->task, t->task->context, t->thread_code, 635 t->kstack, ucycles, usuffix, kcycles, ksuffix); 624 636 #endif 625 637 626 638 #ifdef __64_BITS__ 627 printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ", 628 t->tid, t->name, t, thread_states[t->state], t->task, 629 t->task->context, t->thread_code, t->kstack, cycles, suffix); 639 printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" 640 PRIu64 "%c %9" PRIu64 "%c ", t->tid, t->name, t, 641 thread_states[t->state], t->task, t->task->context, t->thread_code, 642 t->kstack, ucycles, usuffix, kcycles, ksuffix); 630 643 #endif 631 644 … … 661 674 #ifdef __32_BITS__ 662 675 printf("tid name address state task " 663 "ctx code stack cyclescpu "676 "ctx code stack ucycles kcycles cpu " 664 677 "waitqueue\n"); 665 678 printf("------ ---------- ---------- -------- ---------- " 666 "--- ---------- ---------- ---------- ---- "679 "--- ---------- ---------- ---------- ---------- ---- " 667 680 "----------\n"); 668 681 #endif … … 670 683 #ifdef __64_BITS__ 671 684 printf("tid name address state task " 672 "ctx code stack cyclescpu "685 "ctx code stack ucycles kcycles cpu " 673 686 "waitqueue\n"); 674 687 printf("------ ---------- ------------------ -------- ------------------ " 675 "--- ------------------ ------------------ ---------- ---- "688 "--- ------------------ ------------------ ---------- ---------- ---- " 676 689 "------------------\n"); 677 690 #endif … … 706 719 * interrupts must be already disabled. 707 720 * 708 */ 709 void thread_update_accounting(void) 721 * @param user True to update user accounting, false for kernel. 722 */ 723 void thread_update_accounting(bool user) 710 724 { 711 725 uint64_t time = get_cycle(); 712 THREAD->cycles += time - THREAD->last_cycle; 726 if (user) { 727 THREAD->ucycles += time - THREAD->last_cycle; 728 } else { 729 THREAD->kcycles += time - THREAD->last_cycle; 730 } 713 731 THREAD->last_cycle = time; 714 732 } 733 734 static bool thread_search_walker(avltree_node_t *node, void *arg) 735 { 736 thread_t *thread = 737 (thread_t *) avltree_get_instance(node, thread_t, threads_tree_node); 738 thread_iterator_t *iterator = (thread_iterator_t *) arg; 739 740 if (thread->tid == iterator->thread_id) { 741 iterator->thread = thread; 742 return false; 743 } 744 745 return true; 746 } 747 748 /** Find thread structure corresponding to thread ID. 749 * 750 * The threads_lock must be already held by the caller of this function and 751 * interrupts must be disabled. 752 * 753 * @param id Thread ID. 754 * 755 * @return Thread structure address or NULL if there is no such thread ID. 756 * 757 */ 758 thread_t *thread_find_by_id(thread_id_t thread_id) 759 { 760 thread_iterator_t iterator; 761 762 iterator.thread_id = thread_id; 763 iterator.thread = NULL; 764 765 avltree_walk(&threads_tree, thread_search_walker, (void *) &iterator); 766 767 return iterator.thread; 768 } 769 715 770 716 771 /** Process syscall to create new thread. -
kernel/generic/src/synch/waitq.c
r38aaacc2 rf4f866c 54 54 #include <context.h> 55 55 #include <adt/list.h> 56 #include <arch/cycle.h> 56 57 57 58 static void waitq_sleep_timed_out(void *data); … … 373 374 if (!context_save(&THREAD->sleep_interruption_context)) { 374 375 /* Short emulation of scheduler() return code. */ 376 THREAD->last_cycle = get_cycle(); 375 377 spinlock_unlock(&THREAD->lock); 376 378 return ESYNCH_INTERRUPTED; … … 385 387 if (!context_save(&THREAD->sleep_timeout_context)) { 386 388 /* Short emulation of scheduler() return code. */ 389 THREAD->last_cycle = get_cycle(); 387 390 spinlock_unlock(&THREAD->lock); 388 391 return ESYNCH_TIMEOUT; -
kernel/generic/src/syscall/syscall.c
r38aaacc2 rf4f866c 61 61 unative_t rc; 62 62 63 /* Do userpace accounting */ 64 thread_update_accounting(true); 65 63 66 #ifdef CONFIG_UDEBUG 64 67 /* … … 95 98 } 96 99 #endif 100 101 /* Do kernel accounting */ 102 thread_update_accounting(false); 97 103 98 104 return rc; … … 138 144 (syshandler_t) sys_ipc_register_irq, 139 145 (syshandler_t) sys_ipc_unregister_irq, 140 146 141 147 /* Event notification syscalls. */ 142 148 (syshandler_t) sys_event_subscribe, … … 153 159 154 160 /* Sysinfo syscalls */ 155 (syshandler_t) sys_sysinfo_valid, 156 (syshandler_t) sys_sysinfo_value, 161 (syshandler_t) sys_sysinfo_get_tag, 162 (syshandler_t) sys_sysinfo_get_value, 163 (syshandler_t) sys_sysinfo_get_data_size, 164 (syshandler_t) sys_sysinfo_get_data, 157 165 158 166 /* Debug calls */ -
kernel/generic/src/sysinfo/sysinfo.c
r38aaacc2 rf4f866c 37 37 #include <print.h> 38 38 #include <syscall/copy.h> 39 #include <synch/spinlock.h> 40 #include <arch/asm.h> 41 #include <errno.h> 42 43 /** Maximal sysinfo path length */ 44 #define SYSINFO_MAX_PATH 2048 39 45 40 46 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])) 47 48 /** Global sysinfo tree root item */ 49 static sysinfo_item_t *global_root = NULL; 50 51 /** Sysinfo SLAB cache */ 52 static slab_cache_t *sysinfo_item_slab; 53 54 /** Sysinfo spinlock */ 55 SPINLOCK_STATIC_INITIALIZE_NAME(sysinfo_lock, "sysinfo_lock"); 56 57 /** Sysinfo item constructor 58 * 59 */ 60 static int sysinfo_item_constructor(void *obj, int kmflag) 61 { 62 sysinfo_item_t *item = (sysinfo_item_t *) obj; 63 64 item->name = NULL; 65 item->val_type = SYSINFO_VAL_UNDEFINED; 66 item->subtree_type = SYSINFO_SUBTREE_NONE; 67 item->subtree.table = NULL; 68 item->next = NULL; 69 70 return 0; 71 } 72 73 /** Sysinfo item destructor 74 * 75 * Note that the return value is not perfectly correct 76 * since more space might get actually freed thanks 77 * to the disposal of item->name 78 * 79 */ 80 static int sysinfo_item_destructor(void *obj) 81 { 82 sysinfo_item_t *item = (sysinfo_item_t *) obj; 83 84 if (item->name != NULL) 85 free(item->name); 86 87 return 0; 88 } 89 90 /** Initialize sysinfo subsystem 91 * 92 * Create SLAB cache for sysinfo items. 93 * 94 */ 95 void sysinfo_init(void) 96 { 97 sysinfo_item_slab = slab_cache_create("sysinfo_item_slab", 98 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor, 99 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED); 100 } 101 102 /** Recursively find an item in sysinfo tree 103 * 104 * Should be called with interrupts disabled 105 * and sysinfo_lock held. 106 * 107 * @param name Current sysinfo path suffix. 108 * @param subtree Current sysinfo (sub)tree root item. 109 * @param ret If the return value is NULL, this argument 110 * can be either also NULL (i.e. no item was 111 * found and no data was generated) or the 112 * original pointer is used to store the value 113 * generated by a generated subtree function. 114 * @param dry_run Do not actually get any generated 115 * binary data, just calculate the size. 116 * 117 * @return Found item or NULL if no item in the fixed tree 118 * was found (N.B. ret). 119 * 120 */ 121 static sysinfo_item_t *sysinfo_find_item(const char *name, 122 sysinfo_item_t *subtree, sysinfo_return_t **ret, bool dry_run) 123 { 124 ASSERT(subtree != NULL); 125 ASSERT(ret != NULL); 126 127 sysinfo_item_t *cur = subtree; 128 129 /* Walk all siblings */ 130 while (cur != NULL) { 131 size_t i = 0; 132 133 /* Compare name with path */ 134 while ((cur->name[i] != 0) && (name[i] == cur->name[i])) 54 135 i++; 55 136 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); 137 /* Check for perfect name and path match */ 138 if ((name[i] == 0) && (cur->name[i] == 0)) 139 return cur; 140 141 /* Partial match up to the delimiter */ 142 if ((name[i] == '.') && (cur->name[i] == 0)) { 143 /* Look into the subtree */ 144 switch (cur->subtree_type) { 145 case SYSINFO_SUBTREE_TABLE: 146 /* Recursively find in subtree */ 147 return sysinfo_find_item(name + i + 1, 148 cur->subtree.table, ret, dry_run); 149 case SYSINFO_SUBTREE_FUNCTION: 150 /* Get generated data */ 151 **ret = cur->subtree.get_data(name + i + 1, dry_run); 152 return NULL; 153 default: 154 /* Not found, no data generated */ 155 *ret = NULL; 156 return NULL; 157 } 158 } 159 160 cur = cur->next; 161 } 162 163 /* Not found, no data generated */ 164 *ret = NULL; 165 return NULL; 166 } 167 168 /** Recursively create items in sysinfo tree 169 * 170 * Should be called with interrupts disabled 171 * and sysinfo_lock held. 172 * 173 * @param name Current sysinfo path suffix. 174 * @param psubtree Pointer to an already existing (sub)tree root 175 * item or where to store a new tree root item. 176 * 177 * @return Existing or newly allocated sysinfo item or NULL 178 * if the current tree configuration does not allow to 179 * create a new item. 180 * 181 */ 182 static sysinfo_item_t *sysinfo_create_path(const char *name, 183 sysinfo_item_t **psubtree) 184 { 185 ASSERT(psubtree != NULL); 186 187 if (*psubtree == NULL) { 188 /* No parent */ 189 190 size_t i = 0; 191 192 /* Find the first delimiter in name */ 193 while ((name[i] != 0) && (name[i] != '.')) 194 i++; 195 196 *psubtree = 197 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0); 198 ASSERT(*psubtree); 199 200 /* Fill in item name up to the delimiter */ 201 (*psubtree)->name = str_ndup(name, i); 202 ASSERT((*psubtree)->name); 203 204 /* Create subtree items */ 205 if (name[i] == '.') { 206 (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE; 207 return sysinfo_create_path(name + i + 1, 208 &((*psubtree)->subtree.table)); 209 } 210 211 /* No subtree needs to be created */ 212 return *psubtree; 213 } 214 215 sysinfo_item_t *cur = *psubtree; 216 217 /* Walk all siblings */ 218 while (cur != NULL) { 219 size_t i = 0; 220 221 /* Compare name with path */ 222 while ((cur->name[i] != 0) && (name[i] == cur->name[i])) 223 i++; 224 225 /* Check for perfect name and path match 226 * -> item is already present. 227 */ 228 if ((name[i] == 0) && (cur->name[i] == 0)) 229 return cur; 230 231 /* Partial match up to the delimiter */ 232 if ((name[i] == '.') && (cur->name[i] == 0)) { 233 switch (cur->subtree_type) { 234 case SYSINFO_SUBTREE_NONE: 235 /* No subtree yet, create one */ 236 cur->subtree_type = SYSINFO_SUBTREE_TABLE; 237 return sysinfo_create_path(name + i + 1, 238 &(cur->subtree.table)); 239 case SYSINFO_SUBTREE_TABLE: 240 /* Subtree already created, add new sibling */ 241 return sysinfo_create_path(name + i + 1, 242 &(cur->subtree.table)); 243 default: 244 /* Subtree items handled by a function, this 245 * cannot be overriden by a constant item. 246 */ 247 return NULL; 248 } 249 } 250 251 /* No match and no more siblings to check 252 * -> create a new sibling item. 253 */ 254 if (cur->next == NULL) { 255 /* Find the first delimiter in name */ 256 i = 0; 257 while ((name[i] != 0) && (name[i] != '.')) 258 i++; 62 259 63 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 64 // return NULL; 260 sysinfo_item_t *item = 261 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0); 262 ASSERT(item); 65 263 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; 264 cur->next = item; 82 265 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++; 266 /* Fill in item name up to the delimiter */ 267 item->name = str_ndup(name, i); 268 ASSERT(item->name); 91 269 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)); 270 /* Create subtree items */ 271 if (name[i] == '.') { 272 item->subtree_type = SYSINFO_SUBTREE_TABLE; 273 return sysinfo_create_path(name + i + 1, 274 &(item->subtree.table)); 125 275 } 126 276 127 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 128 // return NULL; 129 130 return NULL; 277 /* No subtree needs to be created */ 278 return item; 131 279 } 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; 159 return item; 160 } else 161 subtree = subtree->next; 162 } 163 164 panic("Not reached."); 280 281 cur = cur->next; 282 } 283 284 /* Unreachable */ 285 ASSERT(false); 165 286 return NULL; 166 287 } 167 288 168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val) 169 { 289 /** Set sysinfo item with a constant numeric value 290 * 291 * @param name Sysinfo path. 292 * @param root Pointer to the root item or where to store 293 * a new root item (NULL for global sysinfo root). 294 * @param val Value to store in the item. 295 * 296 */ 297 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, 298 unative_t val) 299 { 300 /* Protect sysinfo tree consistency */ 301 ipl_t ipl = interrupts_disable(); 302 spinlock_lock(&sysinfo_lock); 303 170 304 if (root == NULL) 171 root = &_root; 172 173 /* If already created create only returns pointer 174 If not, create it */ 305 root = &global_root; 306 175 307 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; 308 if (item != NULL) { 179 309 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 { 310 item->val.val = val; 311 } 312 313 spinlock_unlock(&sysinfo_lock); 314 interrupts_restore(ipl); 315 } 316 317 /** Set sysinfo item with a constant binary data 318 * 319 * Note that sysinfo only stores the pointer to the 320 * binary data and does not touch it in any way. The 321 * data should be static and immortal. 322 * 323 * @param name Sysinfo path. 324 * @param root Pointer to the root item or where to store 325 * a new root item (NULL for global sysinfo root). 326 * @param data Binary data. 327 * @param size Size of the binary data. 328 * 329 */ 330 void sysinfo_set_item_data(const char *name, sysinfo_item_t **root, 331 void *data, size_t size) 332 { 333 /* Protect sysinfo tree consistency */ 334 ipl_t ipl = interrupts_disable(); 335 spinlock_lock(&sysinfo_lock); 336 185 337 if (root == NULL) 186 root = &_root; 187 188 /* If already created create only returns pointer 189 If not, create it */ 338 root = &global_root; 339 190 340 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 198 341 if (item != NULL) { 342 item->val_type = SYSINFO_VAL_DATA; 343 item->val.data.data = data; 344 item->val.data.size = size; 345 } 346 347 spinlock_unlock(&sysinfo_lock); 348 interrupts_restore(ipl); 349 } 350 351 /** Set sysinfo item with a generated numeric value 352 * 353 * @param name Sysinfo path. 354 * @param root Pointer to the root item or where to store 355 * a new root item (NULL for global sysinfo root). 356 * @param fn Numeric value generator function. 357 * 358 */ 359 void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root, 360 sysinfo_fn_val_t fn) 361 { 362 /* Protect sysinfo tree consistency */ 363 ipl_t ipl = interrupts_disable(); 364 spinlock_lock(&sysinfo_lock); 365 366 if (root == NULL) 367 root = &global_root; 368 369 sysinfo_item_t *item = sysinfo_create_path(name, root); 370 if (item != NULL) { 371 item->val_type = SYSINFO_VAL_FUNCTION_VAL; 372 item->val.fn_val = fn; 373 } 374 375 spinlock_unlock(&sysinfo_lock); 376 interrupts_restore(ipl); 377 } 378 379 /** Set sysinfo item with a generated binary data 380 * 381 * Note that each time the generator function is called 382 * it is supposed to return a new dynamically allocated 383 * data. This data is then freed by sysinfo in the context 384 * of the current sysinfo request. 385 * 386 * @param name Sysinfo path. 387 * @param root Pointer to the root item or where to store 388 * a new root item (NULL for global sysinfo root). 389 * @param fn Binary data generator function. 390 * 391 */ 392 void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root, 393 sysinfo_fn_data_t fn) 394 { 395 /* Protect sysinfo tree consistency */ 396 ipl_t ipl = interrupts_disable(); 397 spinlock_lock(&sysinfo_lock); 398 399 if (root == NULL) 400 root = &global_root; 401 402 sysinfo_item_t *item = sysinfo_create_path(name, root); 403 if (item != NULL) { 404 item->val_type = SYSINFO_VAL_FUNCTION_DATA; 405 item->val.fn_data = fn; 406 } 407 408 spinlock_unlock(&sysinfo_lock); 409 interrupts_restore(ipl); 410 } 411 412 /** Set sysinfo item with an undefined value 413 * 414 * @param name Sysinfo path. 415 * @param root Pointer to the root item or where to store 416 * a new root item (NULL for global sysinfo root). 417 * 418 */ 199 419 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root) 200 420 { 421 /* Protect sysinfo tree consistency */ 422 ipl_t ipl = interrupts_disable(); 423 spinlock_lock(&sysinfo_lock); 424 201 425 if (root == NULL) 202 root = &_root; 203 204 /* If already created create only returns pointer 205 If not, create it */ 426 root = &global_root; 427 206 428 sysinfo_item_t *item = sysinfo_create_path(name, root); 207 208 429 if (item != NULL) 209 430 item->val_type = SYSINFO_VAL_UNDEFINED; 210 } 211 212 213 void sysinfo_dump(sysinfo_item_t **proot, int depth) 214 { 215 sysinfo_item_t *root; 216 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) { 431 432 spinlock_unlock(&sysinfo_lock); 433 interrupts_restore(ipl); 434 } 435 436 /** Set sysinfo item with a generated subtree 437 * 438 * @param name Sysinfo path. 439 * @param root Pointer to the root item or where to store 440 * a new root item (NULL for global sysinfo root). 441 * @param fn Subtree generator function. 442 * 443 */ 444 void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root, 445 sysinfo_fn_subtree_t fn) 446 { 447 /* Protect sysinfo tree consistency */ 448 ipl_t ipl = interrupts_disable(); 449 spinlock_lock(&sysinfo_lock); 450 451 if (root == NULL) 452 root = &global_root; 453 454 sysinfo_item_t *item = sysinfo_create_path(name, root); 455 456 /* Change the type of the subtree only if it is not already 457 a fixed subtree */ 458 if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) { 459 item->subtree_type = SYSINFO_SUBTREE_FUNCTION; 460 item->subtree.get_data = fn; 461 } 462 463 spinlock_unlock(&sysinfo_lock); 464 interrupts_restore(ipl); 465 } 466 467 /** Sysinfo dump indentation helper routine 468 * 469 * @param depth Number of indentation characters to print. 470 * 471 */ 472 static void sysinfo_indent(unsigned int depth) 473 { 474 unsigned int i; 475 for (i = 0; i < depth; i++) 476 printf(" "); 477 } 478 479 /** Dump the structure of sysinfo tree 480 * 481 * Should be called with interrupts disabled 482 * and sysinfo_lock held. Because this routine 483 * might take a reasonable long time to proceed, 484 * having the spinlock held is not optimal, but 485 * there is no better simple solution. 486 * 487 * @param root Root item of the current (sub)tree. 488 * @param depth Current depth in the sysinfo tree. 489 * 490 */ 491 static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth) 492 { 493 sysinfo_item_t *cur = root; 494 495 /* Walk all siblings */ 496 while (cur != NULL) { 497 sysinfo_indent(depth); 498 499 unative_t val; 500 size_t size; 501 502 /* Display node value and type */ 503 switch (cur->val_type) { 231 504 case SYSINFO_VAL_UNDEFINED: 232 val = 0; 233 vtype = "UND"; 505 printf("+ %s\n", cur->name); 234 506 break; 235 507 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; 508 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name, 509 cur->val.val, cur->val.val); 510 break; 511 case SYSINFO_VAL_DATA: 512 printf("+ %s (%" PRIs" bytes)\n", cur->name, 513 cur->val.data.size); 514 break; 515 case SYSINFO_VAL_FUNCTION_VAL: 516 val = cur->val.fn_val(cur); 517 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n", 518 cur->name, val, val); 519 break; 520 case SYSINFO_VAL_FUNCTION_DATA: 521 /* N.B.: No data was actually returned (only a dry run) */ 522 (void) cur->val.fn_data(cur, &size, true); 523 printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name, 524 size); 525 break; 526 default: 527 printf("+ %s [unknown]\n", cur->name); 243 528 } 244 529 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 530 /* Recursivelly nest into the subtree */ 531 switch (cur->subtree_type) { 532 case SYSINFO_SUBTREE_NONE: 533 break; 534 case SYSINFO_SUBTREE_TABLE: 535 sysinfo_dump_internal(cur->subtree.table, depth + 1); 536 break; 537 case SYSINFO_SUBTREE_FUNCTION: 538 sysinfo_indent(depth + 1); 539 printf("+ [generated subtree]\n"); 540 break; 541 default: 542 sysinfo_indent(depth + 1); 543 printf("+ [unknown subtree]\n"); 544 } 545 546 cur = cur->next; 547 } 548 } 549 550 /** Dump the structure of sysinfo tree 551 * 552 * @param root Root item of the sysinfo (sub)tree. 553 * If it is NULL then consider the global 554 * sysinfo tree. 555 * 556 */ 557 void sysinfo_dump(sysinfo_item_t *root) 558 { 559 /* Avoid other functions to mess with sysinfo 560 while we are dumping it */ 561 ipl_t ipl = interrupts_disable(); 562 spinlock_lock(&sysinfo_lock); 563 263 564 if (root == NULL) 264 root = &_root; 265 266 sysinfo_item_t *item = sysinfo_find_item(name, *root); 565 sysinfo_dump_internal(global_root, 0); 566 else 567 sysinfo_dump_internal(root, 0); 568 569 spinlock_unlock(&sysinfo_lock); 570 interrupts_restore(ipl); 571 } 572 573 /** Return sysinfo item value determined by name 574 * 575 * Should be called with interrupts disabled 576 * and sysinfo_lock held. 577 * 578 * @param name Sysinfo path. 579 * @param root Root item of the sysinfo (sub)tree. 580 * If it is NULL then consider the global 581 * sysinfo tree. 582 * @param dry_run Do not actually get any generated 583 * binary data, just calculate the size. 584 * 585 * @return Item value (constant or generated). 586 * 587 */ 588 static sysinfo_return_t sysinfo_get_item(const char *name, 589 sysinfo_item_t **root, bool dry_run) 590 { 591 if (root == NULL) 592 root = &global_root; 593 594 /* Try to find the item or generate data */ 595 sysinfo_return_t ret; 596 sysinfo_return_t *ret_ptr = &ret; 597 sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr, 598 dry_run); 267 599 268 600 if (item != NULL) { 269 if (item->val_type == SYSINFO_VAL_UNDEFINED) 270 return ret; 601 /* Item found in the fixed sysinfo tree */ 602 603 ret.tag = item->val_type; 604 switch (item->val_type) { 605 case SYSINFO_VAL_UNDEFINED: 606 break; 607 case SYSINFO_VAL_VAL: 608 ret.val = item->val.val; 609 break; 610 case SYSINFO_VAL_DATA: 611 ret.data = item->val.data; 612 break; 613 case SYSINFO_VAL_FUNCTION_VAL: 614 ret.val = item->val.fn_val(item); 615 break; 616 case SYSINFO_VAL_FUNCTION_DATA: 617 ret.data.data = item->val.fn_data(item, &ret.data.size, 618 dry_run); 619 break; 620 } 621 } else { 622 /* No item in the fixed sysinfo tree */ 623 if (ret_ptr == NULL) { 624 /* Even no data was generated */ 625 ret.tag = SYSINFO_VAL_UNDEFINED; 626 } 627 } 628 629 return ret; 630 } 631 632 /** Return sysinfo item determined by name from user space 633 * 634 * Should be called with interrupts disabled 635 * and sysinfo_lock held. The path string passed from 636 * the user space has to be properly null-terminated 637 * (the last passed character must be null). 638 * 639 * @param ptr Sysinfo path in the user address space. 640 * @param size Size of the path string. 641 * @param dry_run Do not actually get any generated 642 * binary data, just calculate the size. 643 * 644 */ 645 static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size, 646 bool dry_run) 647 { 648 sysinfo_return_t ret; 649 ret.tag = SYSINFO_VAL_UNDEFINED; 650 651 if (size > SYSINFO_MAX_PATH) 652 return ret; 653 654 char *path = (char *) malloc(size + 1, 0); 655 ASSERT(path); 656 657 if ((copy_from_uspace(path, ptr, size + 1) == 0) 658 && (path[size] == 0)) 659 ret = sysinfo_get_item(path, NULL, dry_run); 660 661 free(path); 662 return ret; 663 } 664 665 /** Get the sysinfo value type (syscall) 666 * 667 * The path string passed from the user space has 668 * to be properly null-terminated (the last passed 669 * character must be null). 670 * 671 * @param path_ptr Sysinfo path in the user address space. 672 * @param path_size Size of the path string. 673 * 674 * @return Item value type. 675 * 676 */ 677 unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size) 678 { 679 /* Avoid other functions to mess with sysinfo 680 while we are reading it */ 681 ipl_t ipl = interrupts_disable(); 682 spinlock_lock(&sysinfo_lock); 683 684 /* Get the item. 685 686 N.B.: There is no need to free any potential generated 687 binary data since we request a dry run */ 688 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true); 689 690 /* Map generated value types to constant types 691 (user space does not care whether the 692 value is constant or generated) */ 693 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL) 694 ret.tag = SYSINFO_VAL_VAL; 695 else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA) 696 ret.tag = SYSINFO_VAL_DATA; 697 698 spinlock_unlock(&sysinfo_lock); 699 interrupts_restore(ipl); 700 701 return (unative_t) ret.tag; 702 } 703 704 /** Get the sysinfo numerical value (syscall) 705 * 706 * The path string passed from the user space has 707 * to be properly null-terminated (the last passed 708 * character must be null). 709 * 710 * @param path_ptr Sysinfo path in the user address space. 711 * @param path_size Size of the path string. 712 * @param value_ptr User space pointer where to store the 713 * numberical value. 714 * 715 * @return Error code (EOK in case of no error). 716 * 717 */ 718 unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size, 719 void *value_ptr) 720 { 721 /* Avoid other functions to mess with sysinfo 722 while we are reading it */ 723 ipl_t ipl = interrupts_disable(); 724 spinlock_lock(&sysinfo_lock); 725 726 /* Get the item. 727 728 N.B.: There is no need to free any potential generated 729 binary data since we request a dry run */ 730 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true); 731 int rc; 732 733 /* Only constant or generated numerical value is returned */ 734 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL)) 735 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val)); 736 else 737 rc = EINVAL; 738 739 spinlock_unlock(&sysinfo_lock); 740 interrupts_restore(ipl); 741 742 return (unative_t) rc; 743 } 744 745 /** Get the sysinfo binary data size (syscall) 746 * 747 * The path string passed from the user space has 748 * to be properly null-terminated (the last passed 749 * character must be null). 750 * 751 * @param path_ptr Sysinfo path in the user address space. 752 * @param path_size Size of the path string. 753 * @param size_ptr User space pointer where to store the 754 * binary data size. 755 * 756 * @return Error code (EOK in case of no error). 757 * 758 */ 759 unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size, 760 void *size_ptr) 761 { 762 /* Avoid other functions to mess with sysinfo 763 while we are reading it */ 764 ipl_t ipl = interrupts_disable(); 765 spinlock_lock(&sysinfo_lock); 766 767 /* Get the item. 768 769 N.B.: There is no need to free any potential generated 770 binary data since we request a dry run */ 771 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true); 772 int rc; 773 774 /* Only the size of constant or generated binary data is considered */ 775 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) 776 rc = copy_to_uspace(size_ptr, &ret.data.size, 777 sizeof(ret.data.size)); 778 else 779 rc = EINVAL; 780 781 spinlock_unlock(&sysinfo_lock); 782 interrupts_restore(ipl); 783 784 return (unative_t) rc; 785 } 786 787 /** Get the sysinfo binary data (syscall) 788 * 789 * The path string passed from the user space has 790 * to be properly null-terminated (the last passed 791 * character must be null). 792 * 793 * The user space buffer must be sized exactly according 794 * to the size of the binary data, otherwise the request 795 * fails. 796 * 797 * @param path_ptr Sysinfo path in the user address space. 798 * @param path_size Size of the path string. 799 * @param buffer_ptr User space pointer to the buffer where 800 * to store the binary data. 801 * @param buffer_size User space buffer size. 802 * 803 * @return Error code (EOK in case of no error). 804 * 805 */ 806 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size, 807 void *buffer_ptr, size_t buffer_size) 808 { 809 /* Avoid other functions to mess with sysinfo 810 while we are reading it */ 811 ipl_t ipl = interrupts_disable(); 812 spinlock_lock(&sysinfo_lock); 813 814 /* Get the item */ 815 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, false); 816 int rc; 817 818 /* Only constant or generated binary data is considered */ 819 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) { 820 /* Check destination buffer size */ 821 if (ret.data.size == buffer_size) 822 rc = copy_to_uspace(buffer_ptr, ret.data.data, 823 ret.data.size); 271 824 else 272 ret.valid = true; 273 274 if (item->val_type == SYSINFO_VAL_VAL) 275 ret.val = item->val.val; 276 else 277 ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item); 278 } 279 return ret; 280 } 281 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; 825 rc = ENOMEM; 826 } else 827 rc = EINVAL; 828 829 /* N.B.: The generated binary data should be freed */ 830 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL)) 831 free(ret.data.data); 832 833 spinlock_unlock(&sysinfo_lock); 834 interrupts_restore(ipl); 835 836 return (unative_t) rc; 316 837 } 317 838 -
kernel/generic/src/time/clock.c
r38aaacc2 rf4f866c 86 86 uptime->seconds1 = 0; 87 87 uptime->seconds2 = 0; 88 uptime->useconds = 0; 88 uptime->useconds = 0; 89 89 90 90 clock_parea.pbase = (uintptr_t) faddr; … … 137 137 size_t missed_clock_ticks = CPU->missed_clock_ticks; 138 138 unsigned int i; 139 140 /* Account lost ticks to CPU usage */ 141 if (CPU->idle) { 142 ASSERT(missed_clock_ticks == 0); 143 CPU->idle_ticks++; 144 } else { 145 CPU->busy_ticks += missed_clock_ticks + 1; 146 } 147 CPU->idle = false; 139 148 140 149 /*
Note:
See TracChangeset
for help on using the changeset viewer.