Changeset b412168 in mainline
- Timestamp:
- 2014-11-17T03:25:04Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6069061
- Parents:
- ef3da5a (diff), 5042706 (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. - Files:
-
- 45 added
- 34 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
ref3da5a rb412168 168 168 169 169 RD_APPS_NON_ESSENTIAL = \ 170 $(USPACE_PATH)/app/barber/barber \ 170 171 $(USPACE_PATH)/app/bithenge/bithenge \ 171 172 $(USPACE_PATH)/app/blkdump/blkdump \ -
kernel/generic/src/sysinfo/stats.c
ref3da5a rb412168 80 80 static mutex_t load_lock; 81 81 82 /** Get system uptime83 *84 * @param item Sysinfo item (unused).85 * @param data Unused.86 *87 * @return System uptime (in secords).88 *89 */90 static sysarg_t get_stats_uptime(struct sysinfo_item *item, void *data)91 {92 /* This doesn't have to be very accurate */93 return uptime->seconds1;94 }95 96 82 /** Get statistics of all CPUs 97 83 * … … 818 804 mutex_initialize(&load_lock, MUTEX_PASSIVE); 819 805 820 sysinfo_set_item_gen_val("system.uptime", NULL, get_stats_uptime, NULL);821 806 sysinfo_set_item_gen_data("system.cpus", NULL, get_stats_cpus, NULL); 822 807 sysinfo_set_item_gen_data("system.physmem", NULL, get_stats_physmem, NULL); -
uspace/Makefile
ref3da5a rb412168 34 34 35 35 DIRS = \ 36 app/barber \ 36 37 app/bdsh \ 37 38 app/bithenge \ … … 211 212 lib/fmtutil \ 212 213 lib/scsi \ 214 lib/compress \ 213 215 lib/softint \ 214 216 lib/softfloat \ -
uspace/Makefile.common
ref3da5a rb412168 144 144 LIBNIC_PREFIX = $(LIB_PREFIX)/nic 145 145 LIBMINIX_PREFIX = $(LIB_PREFIX)/minix 146 LIBCOMPRESS_PREFIX = $(LIB_PREFIX)/compress 146 147 147 148 LIBSCSI_PREFIX = $(LIB_PREFIX)/scsi -
uspace/app/bnchmark/bnchmark.c
ref3da5a rb412168 62 62 { 63 63 struct timeval start_time; 64 int rc; 65 rc = gettimeofday(&start_time, NULL); 66 if (rc != EOK) { 67 fprintf(stderr, "gettimeofday failed\n"); 68 return rc; 69 } 70 71 rc = fn(data); 64 gettimeofday(&start_time, NULL); 65 66 int rc = fn(data); 72 67 if (rc != EOK) { 73 68 fprintf(stderr, "measured function failed\n"); 74 69 return rc; 75 70 } 76 71 77 72 struct timeval final_time; 78 rc = gettimeofday(&final_time, NULL); 79 if (rc != EOK) { 80 fprintf(stderr, "gettimeofday failed\n"); 81 return rc; 82 } 73 gettimeofday(&final_time, NULL); 83 74 84 75 /* Calculate time difference in milliseconds */ … … 92 83 char *path = (char *) data; 93 84 char *buf = malloc(BUFSIZE); 94 95 if (buf == NULL) {85 86 if (buf == NULL) 96 87 return ENOMEM; 97 }98 88 99 89 FILE *file = fopen(path, "r"); -
uspace/app/init/init.c
ref3da5a rb412168 355 355 int rc = compositor(HID_INPUT, HID_COMPOSITOR_SERVER); 356 356 if (rc == EOK) { 357 gui_start("/app/barber", HID_COMPOSITOR_SERVER); 357 358 gui_start("/app/vlaunch", HID_COMPOSITOR_SERVER); 358 359 gui_start("/app/vterm", HID_COMPOSITOR_SERVER); -
uspace/app/modplay/modplay.c
ref3da5a rb412168 40 40 #include <stdio.h> 41 41 #include <stdlib.h> 42 #include <protracker.h>43 42 #include <trackmod.h> 44 43 … … 88 87 con = console_init(stdin, stdout); 89 88 90 rc = trackmod_ protracker_load(argv[1], &mod);89 rc = trackmod_module_load(argv[1], &mod); 91 90 if (rc != EOK) { 92 91 printf("Error loading %s.\n", argv[1]); -
uspace/app/nettest1/nettest1.c
ref3da5a rb412168 402 402 403 403 struct timeval time_before; 404 rc = gettimeofday(&time_before, NULL); 405 if (rc != EOK) { 406 fprintf(stderr, "Get time of day error %d\n", rc); 407 return rc; 408 } 404 gettimeofday(&time_before, NULL); 409 405 410 406 nettest1_test(socket_ids, 1, 1); … … 414 410 415 411 struct timeval time_after; 416 rc = gettimeofday(&time_after, NULL); 417 if (rc != EOK) { 418 fprintf(stderr, "Get time of day error %d\n", rc); 419 return rc; 420 } 412 gettimeofday(&time_after, NULL); 421 413 422 414 printf("Tested in %ld microseconds\n", tv_sub(&time_after, -
uspace/app/nettest2/nettest2.c
ref3da5a rb412168 356 356 357 357 struct timeval time_before; 358 rc = gettimeofday(&time_before, NULL); 359 if (rc != EOK) { 360 fprintf(stderr, "Get time of day error %d\n", rc); 361 return rc; 362 } 358 gettimeofday(&time_before, NULL); 363 359 364 360 rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, … … 368 364 369 365 struct timeval time_after; 370 rc = gettimeofday(&time_after, NULL); 371 if (rc != EOK) { 372 fprintf(stderr, "Get time of day error %d\n", rc); 373 return rc; 374 } 366 gettimeofday(&time_after, NULL); 375 367 376 368 if (verbose) … … 380 372 tv_sub(&time_after, &time_before)); 381 373 382 rc = gettimeofday(&time_before, NULL); 383 if (rc != EOK) { 384 fprintf(stderr, "Get time of day error %d\n", rc); 385 return rc; 386 } 374 gettimeofday(&time_before, NULL); 387 375 388 376 rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen, … … 396 384 return rc; 397 385 398 rc = gettimeofday(&time_after, NULL); 399 if (rc != EOK) { 400 fprintf(stderr, "Get time of day error %d\n", rc); 401 return rc; 402 } 386 gettimeofday(&time_after, NULL); 403 387 404 388 if (verbose) -
uspace/app/stats/stats.c
ref3da5a rb412168 191 191 static void print_uptime(void) 192 192 { 193 sysarg_t uptime = stats_get_uptime(); 194 printf("%s: Up %" PRIun " days, %" PRIun " hours, " 195 "%" PRIun " minutes, %" PRIun " seconds\n", NAME, 196 uptime / DAY, (uptime % DAY) / HOUR, 197 (uptime % HOUR) / MINUTE, uptime % MINUTE); 193 struct timeval uptime; 194 getuptime(&uptime); 195 196 printf("%s: Up %ld days, %ld hours, %ld minutes, %ld seconds\n", 197 NAME, uptime.tv_sec / DAY, (uptime.tv_sec % DAY) / HOUR, 198 (uptime.tv_sec % HOUR) / MINUTE, uptime.tv_sec % MINUTE); 198 199 } 199 200 -
uspace/app/tester/ipc/ping_pong.c
ref3da5a rb412168 43 43 44 44 struct timeval start; 45 if (gettimeofday(&start, NULL) != 0) { 46 TPRINTF("\n"); 47 return "Failed getting the time"; 48 } 45 gettimeofday(&start, NULL); 49 46 50 47 uint64_t count = 0; 51 48 while (true) { 52 49 struct timeval now; 53 if (gettimeofday(&now, NULL) != 0) { 54 TPRINTF("\n"); 55 return "Failed getting the time"; 56 } 50 gettimeofday(&now, NULL); 57 51 58 52 if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) -
uspace/app/tester/ipc/starve.c
ref3da5a rb412168 40 40 const char *err = NULL; 41 41 console_ctrl_t *console = console_init(stdin, stdout); 42 if (console == NULL) {42 if (console == NULL) 43 43 return "Failed to init connection with console."; 44 }45 44 46 45 struct timeval start; 47 if (gettimeofday(&start, NULL) != 0) { 48 err = "Failed getting the time"; 49 goto leave; 50 } 46 gettimeofday(&start, NULL); 51 47 52 48 TPRINTF("Intensive computation shall be imagined (for %ds)...\n", DURATION_SECS); … … 54 50 while (true) { 55 51 struct timeval now; 56 if (gettimeofday(&now, NULL) != 0) { 57 err = "Failed getting the time"; 58 goto leave; 59 } 52 gettimeofday(&now, NULL); 60 53 61 54 if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) … … 70 63 } 71 64 } 72 65 73 66 // FIXME - unless a key was pressed, the answer leaked as no one 74 67 // will wait for it. 75 68 // We cannot use async_forget() directly, though. Something like 76 69 // console_forget_pending_kbd_event() shall come here. 77 70 78 71 TPRINTF("Terminating...\n"); 79 80 leave: 72 81 73 console_done(console); 82 74 83 75 return err; 84 76 } -
uspace/app/testread/testread.c
ref3da5a rb412168 123 123 struct timeval prev_time; 124 124 struct timeval start_time; 125 int rc; 126 rc = gettimeofday(&start_time, NULL); 127 if (rc != EOK) { 128 printf("gettimeofday failed\n"); 129 fclose(file); 130 free(buf); 131 return 1; 132 } 125 gettimeofday(&start_time, NULL); 133 126 prev_time = start_time; 134 127 … … 155 148 if (progress && offset >= next_mark) { 156 149 struct timeval cur_time; 157 rc = gettimeofday(&cur_time, NULL); 158 if (rc != EOK) { 159 printf("gettimeofday failed\n"); 160 fclose(file); 161 free(buf); 162 return 1; 163 } 150 gettimeofday(&cur_time, NULL); 151 164 152 uint32_t last_run = cur_time.tv_sec - prev_time.tv_sec; 165 153 uint32_t total_time = cur_time.tv_sec - start_time.tv_sec; … … 178 166 179 167 struct timeval final_time; 180 rc = gettimeofday(&final_time, NULL); 181 if (rc != EOK) { 182 printf("gettimeofday failed\n"); 183 fclose(file); 184 free(buf); 185 return 1; 186 } 168 gettimeofday(&final_time, NULL); 187 169 188 170 uint32_t total_run_time = final_time.tv_sec - start_time.tv_sec; -
uspace/app/top/top.c
ref3da5a rb412168 156 156 /* Get current time */ 157 157 struct timeval time; 158 if (gettimeofday(&time, NULL) != EOK) 159 return "Cannot get time of day"; 158 gettimeofday(&time, NULL); 160 159 161 160 target->hours = (time.tv_sec % DAY) / HOUR; … … 164 163 165 164 /* Get uptime */ 166 sysarg_t uptime = stats_get_uptime(); 167 target->udays = uptime / DAY; 168 target->uhours = (uptime % DAY) / HOUR; 169 target->uminutes = (uptime % HOUR) / MINUTE; 170 target->useconds = uptime % MINUTE; 165 struct timeval uptime; 166 getuptime(&uptime); 167 168 target->udays = uptime.tv_sec / DAY; 169 target->uhours = (uptime.tv_sec % DAY) / HOUR; 170 target->uminutes = (uptime.tv_sec % HOUR) / MINUTE; 171 target->useconds = uptime.tv_sec % MINUTE; 171 172 172 173 /* Get load */ -
uspace/app/vlaunch/vlaunch.c
ref3da5a rb412168 37 37 #include <stdio.h> 38 38 #include <malloc.h> 39 #include <io/pixel.h>40 39 #include <task.h> 41 #include <str.h>42 40 #include <str_error.h> 43 #include <loc.h>44 #include <fibril_synch.h>45 #include <io/pixel.h>46 #include <device/led_dev.h>47 41 48 42 #include <window.h> … … 64 58 #define LOGO_HEIGHT 66 65 59 66 #define PERIOD 100000067 #define COLORS 768 69 60 static char *winreg = NULL; 70 static fibril_timer_t *timer = NULL;71 static list_t led_devs;72 73 static pixel_t colors[COLORS] = {74 PIXEL(0xff, 0xff, 0x00, 0x00),75 PIXEL(0xff, 0x00, 0xff, 0x00),76 PIXEL(0xff, 0x00, 0x00, 0xff),77 PIXEL(0xff, 0xff, 0xff, 0x00),78 PIXEL(0xff, 0xff, 0x00, 0xff),79 PIXEL(0xff, 0x00, 0xff, 0xff),80 PIXEL(0xff, 0xff, 0xff, 0xff)81 };82 83 static unsigned int color = 0;84 85 typedef struct {86 link_t link;87 service_id_t svc_id;88 async_sess_t *sess;89 } led_dev_t;90 61 91 62 static int app_launch(const char *app) … … 129 100 } 130 101 131 static void timer_callback(void *data)132 {133 pixel_t next_color = colors[color];134 135 color++;136 if (color >= COLORS)137 color = 0;138 139 list_foreach(led_devs, link, led_dev_t, dev) {140 if (dev->sess)141 led_dev_color_set(dev->sess, next_color);142 }143 144 fibril_timer_set(timer, PERIOD, timer_callback, NULL);145 }146 147 static void loc_callback(void)148 {149 category_id_t led_cat;150 int rc = loc_category_get_id("led", &led_cat, IPC_FLAG_BLOCKING);151 if (rc != EOK)152 return;153 154 service_id_t *svcs;155 size_t count;156 rc = loc_category_get_svcs(led_cat, &svcs, &count);157 if (rc != EOK)158 return;159 160 for (size_t i = 0; i < count; i++) {161 bool known = false;162 163 /* Determine whether we already know this device. */164 list_foreach(led_devs, link, led_dev_t, dev) {165 if (dev->svc_id == svcs[i]) {166 known = true;167 break;168 }169 }170 171 if (!known) {172 led_dev_t *dev = (led_dev_t *) calloc(1, sizeof(led_dev_t));173 if (!dev)174 continue;175 176 link_initialize(&dev->link);177 dev->svc_id = svcs[i];178 dev->sess = loc_service_connect(EXCHANGE_SERIALIZE, svcs[i], 0);179 180 list_append(&dev->link, &led_devs);181 }182 }183 184 // FIXME: Handle LED device removal185 186 free(svcs);187 }188 189 102 int main(int argc, char *argv[]) 190 103 { 191 104 if (argc < 2) { 192 105 printf("Compositor server not specified.\n"); 193 return 1;194 }195 196 list_initialize(&led_devs);197 int rc = loc_register_cat_change_cb(loc_callback);198 if (rc != EOK) {199 printf("Unable to register callback for device discovery.\n");200 return 1;201 }202 203 timer = fibril_timer_create(NULL);204 if (!timer) {205 printf("Unable to create timer.\n");206 106 return 1; 207 107 } … … 262 162 window_exec(main_window); 263 163 264 fibril_timer_set(timer, PERIOD, timer_callback, NULL);265 266 164 task_retval(0); 267 165 async_manager(); -
uspace/dist/src/c/demos/tetris/shapes.c
ref3da5a rb412168 69 69 70 70 const struct shape shapes[] = { 71 /* 0 */ { 7, 7, { TL, TC, MR }, 0x ff042d},72 /* 1 */ { 8, 8, { TC, TR, ML }, 0x ff9304},73 /* 2 */ { 9, 11, { ML, MR, BC }, 0x beff04},74 /* 3 */ { 3, 3, { TL, TC, ML }, 0x 63ff04},75 /* 4 */ { 12, 14, { ML, BL, MR }, 0x ce04ff},76 /* 5 */ { 15, 17, { ML, BR, MR }, 0xff 04cf},77 /* 6 */ { 18, 18, { ML, MR, 2 }, 0x 7604ff}, /* sticks out */78 /* 7 */ { 0, 0, { TC, ML, BL }, 0x ff042d},79 /* 8 */ { 1, 1, { TC, MR, BR }, 0x ff9304},80 /* 9 */ { 10, 2, { TC, MR, BC }, 0x beff04},81 /* 10 */ { 11, 9, { TC, ML, MR }, 0x beff04},82 /* 11 */ { 2, 10, { TC, ML, BC }, 0x beff04},83 /* 12 */ { 13, 4, { TC, BC, BR }, 0x ce04ff},84 /* 13 */ { 14, 12, { TR, ML, MR }, 0x ce04ff},85 /* 14 */ { 4, 13, { TL, TC, BC }, 0x ce04ff},86 /* 15 */ { 16, 5, { TR, TC, BC }, 0xff 04cf},87 /* 16 */ { 17, 15, { TL, MR, ML }, 0xff 04cf},88 /* 17 */ { 5, 16, { TC, BC, BL }, 0xff 04cf},89 /* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0x 7604ff} /* sticks out */71 /* 0 */ { 7, 7, { TL, TC, MR }, 0x00aaaa}, 72 /* 1 */ { 8, 8, { TC, TR, ML }, 0x00aa00}, 73 /* 2 */ { 9, 11, { ML, MR, BC }, 0xaa5500}, 74 /* 3 */ { 3, 3, { TL, TC, ML }, 0x0000aa}, 75 /* 4 */ { 12, 14, { ML, BL, MR }, 0xaa00aa}, 76 /* 5 */ { 15, 17, { ML, BR, MR }, 0xffa500}, 77 /* 6 */ { 18, 18, { ML, MR, 2 }, 0xaa0000}, /* sticks out */ 78 /* 7 */ { 0, 0, { TC, ML, BL }, 0x00aaaa}, 79 /* 8 */ { 1, 1, { TC, MR, BR }, 0x00aa00}, 80 /* 9 */ { 10, 2, { TC, MR, BC }, 0xaa5500}, 81 /* 10 */ { 11, 9, { TC, ML, MR }, 0xaa5500}, 82 /* 11 */ { 2, 10, { TC, ML, BC }, 0xaa5500}, 83 /* 12 */ { 13, 4, { TC, BC, BR }, 0xaa00aa}, 84 /* 13 */ { 14, 12, { TR, ML, MR }, 0xaa00aa}, 85 /* 14 */ { 4, 13, { TL, TC, BC }, 0xaa00aa}, 86 /* 15 */ { 16, 5, { TR, TC, BC }, 0xffa500}, 87 /* 16 */ { 17, 15, { TL, MR, ML }, 0xffa500}, 88 /* 17 */ { 5, 16, { TC, BC, BL }, 0xffa500}, 89 /* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0xaa0000} /* sticks out */ 90 90 }; 91 91 -
uspace/dist/src/c/demos/top/screen.c
ref3da5a rb412168 37 37 38 38 #include <stdio.h> 39 #include <stdlib.h> 39 40 #include <io/console.h> 40 41 #include <io/style.h> … … 43 44 #include <stats.h> 44 45 #include <inttypes.h> 46 #include <macros.h> 45 47 #include "screen.h" 46 48 #include "top.h" … … 48 50 #define USEC_COUNT 1000000 49 51 50 static sysarg_t warn_col = 0;51 static sysarg_t warn_row = 0;52 52 static suseconds_t timeleft = 0; 53 53 54 54 console_ctrl_t *console; 55 55 56 static sysarg_t warning_col = 0; 57 static sysarg_t warning_row = 0; 58 static suseconds_t warning_timeleft = 0; 59 static char *warning_text = NULL; 60 56 61 static void screen_style_normal(void) 57 62 { … … 64 69 console_flush(console); 65 70 console_set_style(console, STYLE_INVERTED); 71 } 72 73 static void screen_style_emphasis(void) 74 { 75 console_flush(console); 76 console_set_style(console, STYLE_EMPHASIS); 66 77 } 67 78 … … 126 137 void screen_done(void) 127 138 { 139 free(warning_text); 140 warning_text = NULL; 141 128 142 screen_restart(true); 129 143 … … 277 291 } 278 292 279 static inline void print_ tasks_head(void)293 static inline void print_help_head(void) 280 294 { 281 295 screen_style_inverted(); 282 printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]" 283 " [%%user] [%%kern] [name"); 296 printf("Help"); 284 297 screen_newline(); 285 298 screen_style_normal(); 286 299 } 287 300 288 static inline void print_tasks(data_t *data) 289 { 290 sysarg_t cols; 291 sysarg_t rows; 292 screen_get_size(&cols, &rows); 301 static inline void print_help(void) 302 { 303 sysarg_t cols; 304 sysarg_t rows; 305 screen_get_size(&cols, &rows); 306 307 screen_newline(); 308 309 printf("Operation modes:"); 310 screen_newline(); 311 312 printf(" t .. tasks statistics"); 313 screen_newline(); 314 315 printf(" i .. IPC statistics"); 316 screen_newline(); 317 318 printf(" e .. exceptions statistics"); 319 screen_newline(); 320 321 printf(" a .. toggle display of all/hot exceptions"); 322 screen_newline(); 323 324 printf(" h .. toggle this help screen"); 325 screen_newline(); 326 327 screen_newline(); 328 329 printf("Other keys:"); 330 screen_newline(); 331 332 printf(" s .. choose column to sort by"); 333 screen_newline(); 334 335 printf(" r .. toggle reversed sorting"); 336 screen_newline(); 337 338 printf(" q .. quit"); 339 screen_newline(); 293 340 294 341 sysarg_t col; … … 296 343 screen_get_pos(&col, &row); 297 344 298 size_t i;299 for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {300 stats_task_t *task = data->tasks + data->tasks_map[i];301 perc_task_t *perc = data->tasks_perc + data->tasks_map[i];302 303 uint64_t resmem;304 const char *resmem_suffix;305 bin_order_suffix(task->resmem, &resmem, &resmem_suffix, true);306 307 uint64_t virtmem;308 const char *virtmem_suffix;309 bin_order_suffix(task->virtmem, &virtmem, &virtmem_suffix, true);310 311 printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s ",312 task->task_id, task->threads, resmem, resmem_suffix);313 print_percent(perc->resmem, 2);314 printf(" %6" PRIu64 "%s ", virtmem, virtmem_suffix);315 print_percent(perc->virtmem, 2);316 puts(" ");317 print_percent(perc->ucycles, 2);318 puts(" ");319 print_percent(perc->kcycles, 2);320 puts(" ");321 print_string(task->name);322 323 screen_newline();324 }325 326 345 while (row < rows) { 327 346 screen_newline(); … … 330 349 } 331 350 332 static inline void print_ipc_head(void) 333 { 351 static inline void print_table_head(const table_t *table) 352 { 353 sysarg_t cols; 354 sysarg_t rows; 355 screen_get_size(&cols, &rows); 356 334 357 screen_style_inverted(); 335 printf("[taskid] [cls snt] [cls rcv] [ans snt]" 336 " [ans rcv] [irq rcv] [forward] [name"); 358 for (size_t i = 0; i < table->num_columns; i++) { 359 const char *name = table->columns[i].name; 360 int width = table->columns[i].width; 361 if (i != 0) { 362 puts(" "); 363 } 364 if (width == 0) { 365 sysarg_t col; 366 sysarg_t row; 367 screen_get_pos(&col, &row); 368 width = cols - col - 1; 369 } 370 printf("[%-*.*s]", width - 2, width - 2, name); 371 } 337 372 screen_newline(); 338 373 screen_style_normal(); 339 374 } 340 375 341 static inline void print_ ipc(data_t *data)376 static inline void print_table(const table_t *table) 342 377 { 343 378 sysarg_t cols; … … 350 385 351 386 size_t i; 352 for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) { 353 uint64_t call_sent; 354 uint64_t call_received; 355 uint64_t answer_sent; 356 uint64_t answer_received; 357 uint64_t irq_notif_received; 358 uint64_t forwarded; 359 360 char call_sent_suffix; 361 char call_received_suffix; 362 char answer_sent_suffix; 363 char answer_received_suffix; 364 char irq_notif_received_suffix; 365 char forwarded_suffix; 366 367 order_suffix(data->tasks[i].ipc_info.call_sent, &call_sent, 368 &call_sent_suffix); 369 order_suffix(data->tasks[i].ipc_info.call_received, 370 &call_received, &call_received_suffix); 371 order_suffix(data->tasks[i].ipc_info.answer_sent, 372 &answer_sent, &answer_sent_suffix); 373 order_suffix(data->tasks[i].ipc_info.answer_received, 374 &answer_received, &answer_received_suffix); 375 order_suffix(data->tasks[i].ipc_info.irq_notif_received, 376 &irq_notif_received, &irq_notif_received_suffix); 377 order_suffix(data->tasks[i].ipc_info.forwarded, &forwarded, 378 &forwarded_suffix); 379 380 printf("%-8" PRIu64 " %8" PRIu64 "%c %8" PRIu64 "%c" 381 " %8" PRIu64 "%c %8" PRIu64 "%c %8" PRIu64 "%c" 382 " %8" PRIu64 "%c ", data->tasks[i].task_id, 383 call_sent, call_sent_suffix, 384 call_received, call_received_suffix, 385 answer_sent, answer_sent_suffix, 386 answer_received, answer_received_suffix, 387 irq_notif_received, irq_notif_received_suffix, 388 forwarded, forwarded_suffix); 389 print_string(data->tasks[i].name); 390 391 screen_newline(); 387 for (i = 0; (i < table->num_fields) && (row < rows); i++) { 388 size_t column_index = i % table->num_columns; 389 int width = table->columns[column_index].width; 390 field_t *field = &table->fields[i]; 391 392 if (column_index != 0) { 393 puts(" "); 394 } 395 396 if (width == 0) { 397 screen_get_pos(&col, &row); 398 width = cols - col - 1; 399 } 400 401 switch (field->type) { 402 case FIELD_EMPTY: 403 printf("%*s", width, ""); 404 break; 405 case FIELD_UINT: 406 printf("%*" PRIu64, width, field->uint); 407 break; 408 case FIELD_UINT_SUFFIX_BIN: { 409 uint64_t val = field->uint; 410 const char *suffix; 411 width -= 3; 412 bin_order_suffix(val, &val, &suffix, true); 413 printf("%*" PRIu64 "%s", width, val, suffix); 414 break; 415 } 416 case FIELD_UINT_SUFFIX_DEC: { 417 uint64_t val = field->uint; 418 char suffix; 419 width -= 1; 420 order_suffix(val, &val, &suffix); 421 printf("%*" PRIu64 "%c", width, val, suffix); 422 break; 423 } 424 case FIELD_PERCENT: 425 width -= 5; /* nnn.% */ 426 if (width > 2) { 427 printf("%*s", width - 2, ""); 428 width = 2; 429 } 430 print_percent(field->fixed, width); 431 break; 432 case FIELD_STRING: 433 printf("%-*.*s", width, width, field->string); 434 break; 435 } 436 437 if (column_index == table->num_columns - 1) { 438 screen_newline(); 439 row++; 440 } 392 441 } 393 442 … … 398 447 } 399 448 400 static inline void print_excs_head(void) 401 { 402 screen_style_inverted(); 403 printf("[exc ] [count ] [%%count] [cycles ] [%%cycles] [description"); 404 screen_newline(); 405 screen_style_normal(); 406 } 407 408 static inline void print_excs(data_t *data) 449 static inline void print_sort(table_t *table) 409 450 { 410 451 sysarg_t cols; … … 415 456 sysarg_t row; 416 457 screen_get_pos(&col, &row); 417 418 size_t i; 419 for (i = 0; (i < data->exceptions_count) && (row < rows); i++) { 420 /* Filter-out cold exceptions if not instructed otherwise */ 421 if ((!excs_all) && (!data->exceptions[i].hot)) 422 continue; 423 424 uint64_t count; 425 uint64_t cycles; 426 427 char count_suffix; 428 char cycles_suffix; 429 430 order_suffix(data->exceptions[i].count, &count, &count_suffix); 431 order_suffix(data->exceptions[i].cycles, &cycles, &cycles_suffix); 432 433 printf("%-8u %9" PRIu64 "%c ", 434 data->exceptions[i].id, count, count_suffix); 435 print_percent(data->exceptions_perc[i].count, 2); 436 printf(" %9" PRIu64 "%c ", cycles, cycles_suffix); 437 print_percent(data->exceptions_perc[i].cycles, 2); 438 puts(" "); 439 print_string(data->exceptions[i].desc); 440 458 459 size_t num = min(table->num_columns, rows - row); 460 for (size_t i = 0; i < num; i++) { 461 printf("%c - %s", table->columns[i].key, table->columns[i].name); 441 462 screen_newline(); 442 463 row++; … … 449 470 } 450 471 451 static void print_help(void) 452 { 453 sysarg_t cols; 454 sysarg_t rows; 455 screen_get_size(&cols, &rows); 456 457 sysarg_t col; 458 sysarg_t row; 459 screen_get_pos(&col, &row); 460 461 screen_newline(); 462 463 printf("Operation modes:"); 464 screen_newline(); 465 466 printf(" t .. tasks statistics"); 467 screen_newline(); 468 469 printf(" i .. IPC statistics"); 470 screen_newline(); 471 472 printf(" e .. exceptions statistics"); 473 screen_newline(); 474 475 printf(" a .. toggle display of all/hot exceptions"); 476 screen_newline(); 477 478 row += 6; 479 480 while (row < rows) { 481 screen_newline(); 482 row++; 483 } 472 static inline void print_warning(void) 473 { 474 screen_get_pos(&warning_col, &warning_row); 475 if (warning_timeleft > 0) { 476 screen_style_emphasis(); 477 print_string(warning_text); 478 screen_style_normal(); 479 } else { 480 free(warning_text); 481 warning_text = NULL; 482 } 483 screen_newline(); 484 484 } 485 485 … … 492 492 print_cpu_info(data); 493 493 print_physmem_info(data); 494 495 /* Empty row for warnings */ 496 screen_get_pos(&warn_col, &warn_row); 497 screen_newline(); 498 499 switch (op_mode) { 500 case OP_TASKS: 501 print_tasks_head(); 502 print_tasks(data); 494 print_warning(); 495 496 switch (screen_mode) { 497 case SCREEN_TABLE: 498 print_table_head(&data->table); 499 print_table(&data->table); 503 500 break; 504 case OP_IPC: 505 print_ipc_head(); 506 print_ipc(data); 501 case SCREEN_SORT: 502 print_sort(&data->table); 507 503 break; 508 case OP_EXCS: 509 print_excs_head(); 510 print_excs(data); 511 break; 512 case OP_HELP: 513 print_tasks_head(); 504 case SCREEN_HELP: 505 print_help_head(); 514 506 print_help(); 515 507 } … … 518 510 } 519 511 520 void print_warning(const char *fmt, ...) 521 { 522 screen_moveto(warn_col, warn_row); 523 512 void show_warning(const char *fmt, ...) 513 { 514 sysarg_t cols; 515 sysarg_t rows; 516 screen_get_size(&cols, &rows); 517 518 size_t warning_text_size = 1 + cols * sizeof(*warning_text); 519 free(warning_text); 520 warning_text = malloc(warning_text_size); 521 if (!warning_text) 522 return; 523 524 524 va_list args; 525 525 va_start(args, fmt); 526 v printf(fmt, args);526 vsnprintf(warning_text, warning_text_size, fmt, args); 527 527 va_end(args); 528 528 529 screen_newline(); 529 warning_timeleft = 2 * USEC_COUNT; 530 531 screen_moveto(warning_col, warning_row); 532 print_warning(); 530 533 console_flush(console); 531 534 } … … 555 558 cons_event_t event; 556 559 560 warning_timeleft -= timeleft; 557 561 if (!console_get_event_timeout(console, &event, &timeleft)) { 558 562 timeleft = 0; 559 563 return -1; 560 564 } 565 warning_timeleft += timeleft; 561 566 562 567 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS) -
uspace/dist/src/c/demos/top/screen.h
ref3da5a rb412168 44 44 extern void screen_done(void); 45 45 extern void print_data(data_t *); 46 extern void print_warning(const char *, ...)46 extern void show_warning(const char *, ...) 47 47 PRINTF_ATTRIBUTE(1, 2); 48 48 -
uspace/dist/src/c/demos/top/top.c
ref3da5a rb412168 55 55 #define MINUTE 60 56 56 57 op_mode_t op_mode = OP_TASKS; 58 sort_mode_t sort_mode = SORT_TASK_CYCLES; 59 bool excs_all = false; 57 typedef enum { 58 OP_TASKS, 59 OP_IPC, 60 OP_EXCS, 61 } op_mode_t; 62 63 static const column_t task_columns[] = { 64 {"taskid", 't', 8}, 65 {"thrds", 'h', 7}, 66 {"resident", 'r', 10}, 67 {"%resi", 'R', 7}, 68 {"virtual", 'v', 9}, 69 {"%virt", 'V', 7}, 70 {"%user", 'U', 7}, 71 {"%kern", 'K', 7}, 72 {"name", 'd', 0}, 73 }; 74 75 enum { 76 TASK_COL_ID = 0, 77 TASK_COL_NUM_THREADS, 78 TASK_COL_RESIDENT, 79 TASK_COL_PERCENT_RESIDENT, 80 TASK_COL_VIRTUAL, 81 TASK_COL_PERCENT_VIRTUAL, 82 TASK_COL_PERCENT_USER, 83 TASK_COL_PERCENT_KERNEL, 84 TASK_COL_NAME, 85 TASK_NUM_COLUMNS, 86 }; 87 88 static const column_t ipc_columns[] = { 89 {"taskid", 't', 8}, 90 {"cls snt", 'c', 9}, 91 {"cls rcv", 'C', 9}, 92 {"ans snt", 'a', 9}, 93 {"ans rcv", 'A', 9}, 94 {"forward", 'f', 9}, 95 {"name", 'd', 0}, 96 }; 97 98 enum { 99 IPC_COL_TASKID = 0, 100 IPC_COL_CLS_SNT, 101 IPC_COL_CLS_RCV, 102 IPC_COL_ANS_SNT, 103 IPC_COL_ANS_RCV, 104 IPC_COL_FORWARD, 105 IPC_COL_NAME, 106 IPC_NUM_COLUMNS, 107 }; 108 109 static const column_t exception_columns[] = { 110 {"exc", 'e', 8}, 111 {"count", 'n', 10}, 112 {"%count", 'N', 8}, 113 {"cycles", 'c', 10}, 114 {"%cycles", 'C', 9}, 115 {"description", 'd', 0}, 116 }; 117 118 enum { 119 EXCEPTION_COL_ID = 0, 120 EXCEPTION_COL_COUNT, 121 EXCEPTION_COL_PERCENT_COUNT, 122 EXCEPTION_COL_CYCLES, 123 EXCEPTION_COL_PERCENT_CYCLES, 124 EXCEPTION_COL_DESCRIPTION, 125 EXCEPTION_NUM_COLUMNS, 126 }; 127 128 screen_mode_t screen_mode = SCREEN_TABLE; 129 static op_mode_t op_mode = OP_TASKS; 130 static size_t sort_column = TASK_COL_PERCENT_USER; 131 static int sort_reverse = -1; 132 static bool excs_all = false; 60 133 61 134 static const char *read_data(data_t *target) … … 67 140 target->tasks = NULL; 68 141 target->tasks_perc = NULL; 69 target->tasks_map = NULL;70 142 target->threads = NULL; 71 143 target->exceptions = NULL; … … 76 148 target->ecycles_diff = NULL; 77 149 target->ecount_diff = NULL; 150 target->table.name = NULL; 151 target->table.num_columns = 0; 152 target->table.columns = NULL; 153 target->table.num_fields = 0; 154 target->table.fields = NULL; 78 155 79 156 /* Get current time */ 80 157 struct timeval time; 81 if (gettimeofday(&time, NULL) != EOK) 82 return "Cannot get time of day"; 158 gettimeofday(&time, NULL); 83 159 84 160 target->hours = (time.tv_sec % DAY) / HOUR; … … 87 163 88 164 /* Get uptime */ 89 sysarg_t uptime = stats_get_uptime(); 90 target->udays = uptime / DAY; 91 target->uhours = (uptime % DAY) / HOUR; 92 target->uminutes = (uptime % HOUR) / MINUTE; 93 target->useconds = uptime % MINUTE; 165 struct timeval uptime; 166 getuptime(&uptime); 167 168 target->udays = uptime.tv_sec / DAY; 169 target->uhours = (uptime.tv_sec % DAY) / HOUR; 170 target->uminutes = (uptime.tv_sec % HOUR) / MINUTE; 171 target->useconds = uptime.tv_sec % MINUTE; 94 172 95 173 /* Get load */ … … 117 195 if (target->tasks_perc == NULL) 118 196 return "Not enough memory for task utilization"; 119 120 target->tasks_map =121 (size_t *) calloc(target->tasks_count, sizeof(size_t));122 if (target->tasks_map == NULL)123 return "Not enough memory for task map";124 197 125 198 /* Get threads */ … … 289 362 static int cmp_data(void *a, void *b, void *arg) 290 363 { 291 size_t ia = *((size_t *) a); 292 size_t ib = *((size_t *) b); 293 data_t *data = (data_t *) arg; 294 295 uint64_t acycles = data->ucycles_diff[ia] + data->kcycles_diff[ia]; 296 uint64_t bcycles = data->ucycles_diff[ib] + data->kcycles_diff[ib]; 297 298 if (acycles > bcycles) 299 return -1; 300 301 if (acycles < bcycles) 302 return 1; 303 364 field_t *fa = (field_t *)a + sort_column; 365 field_t *fb = (field_t *)b + sort_column; 366 367 if (fa->type > fb->type) 368 return 1 * sort_reverse; 369 370 if (fa->type < fb->type) 371 return -1 * sort_reverse; 372 373 switch (fa->type) { 374 case FIELD_EMPTY: 375 return 0; 376 case FIELD_UINT_SUFFIX_BIN: /* fallthrough */ 377 case FIELD_UINT_SUFFIX_DEC: /* fallthrough */ 378 case FIELD_UINT: 379 if (fa->uint > fb->uint) 380 return 1 * sort_reverse; 381 if (fa->uint < fb->uint) 382 return -1 * sort_reverse; 383 return 0; 384 case FIELD_PERCENT: 385 if (fa->fixed.upper * fb->fixed.lower 386 > fb->fixed.upper * fa->fixed.lower) 387 return 1 * sort_reverse; 388 if (fa->fixed.upper * fb->fixed.lower 389 < fb->fixed.upper * fa->fixed.lower) 390 return -1 * sort_reverse; 391 return 0; 392 case FIELD_STRING: 393 return str_cmp(fa->string, fb->string) * sort_reverse; 394 } 395 304 396 return 0; 305 397 } 306 398 307 static void sort_data(data_t *data) 308 { 309 size_t i; 310 311 for (i = 0; i < data->tasks_count; i++) 312 data->tasks_map[i] = i; 313 314 qsort((void *) data->tasks_map, data->tasks_count, 315 sizeof(size_t), cmp_data, (void *) data); 399 static void sort_table(table_t *table) 400 { 401 if (sort_column >= table->num_columns) 402 sort_column = 0; 403 /* stable sort is probably best, so we use gsort */ 404 gsort((void *) table->fields, table->num_fields / table->num_columns, 405 sizeof(field_t) * table->num_columns, cmp_data, NULL); 406 } 407 408 static const char *fill_task_table(data_t *data) 409 { 410 data->table.name = "Tasks"; 411 data->table.num_columns = TASK_NUM_COLUMNS; 412 data->table.columns = task_columns; 413 data->table.num_fields = data->tasks_count * TASK_NUM_COLUMNS; 414 data->table.fields = calloc(data->table.num_fields, 415 sizeof(field_t)); 416 if (data->table.fields == NULL) 417 return "Not enough memory for table fields"; 418 419 field_t *field = data->table.fields; 420 for (size_t i = 0; i < data->tasks_count; i++) { 421 stats_task_t *task = &data->tasks[i]; 422 perc_task_t *perc = &data->tasks_perc[i]; 423 field[TASK_COL_ID].type = FIELD_UINT; 424 field[TASK_COL_ID].uint = task->task_id; 425 field[TASK_COL_NUM_THREADS].type = FIELD_UINT; 426 field[TASK_COL_NUM_THREADS].uint = task->threads; 427 field[TASK_COL_RESIDENT].type = FIELD_UINT_SUFFIX_BIN; 428 field[TASK_COL_RESIDENT].uint = task->resmem; 429 field[TASK_COL_PERCENT_RESIDENT].type = FIELD_PERCENT; 430 field[TASK_COL_PERCENT_RESIDENT].fixed = perc->resmem; 431 field[TASK_COL_VIRTUAL].type = FIELD_UINT_SUFFIX_BIN; 432 field[TASK_COL_VIRTUAL].uint = task->virtmem; 433 field[TASK_COL_PERCENT_VIRTUAL].type = FIELD_PERCENT; 434 field[TASK_COL_PERCENT_VIRTUAL].fixed = perc->virtmem; 435 field[TASK_COL_PERCENT_USER].type = FIELD_PERCENT; 436 field[TASK_COL_PERCENT_USER].fixed = perc->ucycles; 437 field[TASK_COL_PERCENT_KERNEL].type = FIELD_PERCENT; 438 field[TASK_COL_PERCENT_KERNEL].fixed = perc->kcycles; 439 field[TASK_COL_NAME].type = FIELD_STRING; 440 field[TASK_COL_NAME].string = task->name; 441 field += TASK_NUM_COLUMNS; 442 } 443 444 return NULL; 445 } 446 447 static const char *fill_ipc_table(data_t *data) 448 { 449 data->table.name = "IPC"; 450 data->table.num_columns = IPC_NUM_COLUMNS; 451 data->table.columns = ipc_columns; 452 data->table.num_fields = data->tasks_count * IPC_NUM_COLUMNS; 453 data->table.fields = calloc(data->table.num_fields, 454 sizeof(field_t)); 455 if (data->table.fields == NULL) 456 return "Not enough memory for table fields"; 457 458 field_t *field = data->table.fields; 459 for (size_t i = 0; i < data->tasks_count; i++) { 460 field[IPC_COL_TASKID].type = FIELD_UINT; 461 field[IPC_COL_TASKID].uint = data->tasks[i].task_id; 462 field[IPC_COL_CLS_SNT].type = FIELD_UINT_SUFFIX_DEC; 463 field[IPC_COL_CLS_SNT].uint = data->tasks[i].ipc_info.call_sent; 464 field[IPC_COL_CLS_RCV].type = FIELD_UINT_SUFFIX_DEC; 465 field[IPC_COL_CLS_RCV].uint = data->tasks[i].ipc_info.call_received; 466 field[IPC_COL_ANS_SNT].type = FIELD_UINT_SUFFIX_DEC; 467 field[IPC_COL_ANS_SNT].uint = data->tasks[i].ipc_info.answer_sent; 468 field[IPC_COL_ANS_RCV].type = FIELD_UINT_SUFFIX_DEC; 469 field[IPC_COL_ANS_RCV].uint = data->tasks[i].ipc_info.answer_received; 470 field[IPC_COL_FORWARD].type = FIELD_UINT_SUFFIX_DEC; 471 field[IPC_COL_FORWARD].uint = data->tasks[i].ipc_info.forwarded; 472 field[IPC_COL_NAME].type = FIELD_STRING; 473 field[IPC_COL_NAME].string = data->tasks[i].name; 474 field += IPC_NUM_COLUMNS; 475 } 476 477 return NULL; 478 } 479 480 static const char *fill_exception_table(data_t *data) 481 { 482 data->table.name = "Exceptions"; 483 data->table.num_columns = EXCEPTION_NUM_COLUMNS; 484 data->table.columns = exception_columns; 485 data->table.num_fields = data->exceptions_count * 486 EXCEPTION_NUM_COLUMNS; 487 data->table.fields = calloc(data->table.num_fields, sizeof(field_t)); 488 if (data->table.fields == NULL) 489 return "Not enough memory for table fields"; 490 491 field_t *field = data->table.fields; 492 for (size_t i = 0; i < data->exceptions_count; i++) { 493 if (!excs_all && !data->exceptions[i].hot) 494 continue; 495 field[EXCEPTION_COL_ID].type = FIELD_UINT; 496 field[EXCEPTION_COL_ID].uint = data->exceptions[i].id; 497 field[EXCEPTION_COL_COUNT].type = FIELD_UINT_SUFFIX_DEC; 498 field[EXCEPTION_COL_COUNT].uint = data->exceptions[i].count; 499 field[EXCEPTION_COL_PERCENT_COUNT].type = FIELD_PERCENT; 500 field[EXCEPTION_COL_PERCENT_COUNT].fixed = data->exceptions_perc[i].count; 501 field[EXCEPTION_COL_CYCLES].type = FIELD_UINT_SUFFIX_DEC; 502 field[EXCEPTION_COL_CYCLES].uint = data->exceptions[i].cycles; 503 field[EXCEPTION_COL_PERCENT_CYCLES].type = FIELD_PERCENT; 504 field[EXCEPTION_COL_PERCENT_CYCLES].fixed = data->exceptions_perc[i].cycles; 505 field[EXCEPTION_COL_DESCRIPTION].type = FIELD_STRING; 506 field[EXCEPTION_COL_DESCRIPTION].string = data->exceptions[i].desc; 507 field += EXCEPTION_NUM_COLUMNS; 508 } 509 510 /* in case any cold exceptions were ignored */ 511 data->table.num_fields = field - data->table.fields; 512 513 return NULL; 514 } 515 516 static const char *fill_table(data_t *data) 517 { 518 if (data->table.fields != NULL) { 519 free(data->table.fields); 520 data->table.fields = NULL; 521 } 522 523 switch (op_mode) { 524 case OP_TASKS: 525 return fill_task_table(data); 526 case OP_IPC: 527 return fill_ipc_table(data); 528 case OP_EXCS: 529 return fill_exception_table(data); 530 } 531 return NULL; 316 532 } 317 533 … … 356 572 if (target->ecount_diff != NULL) 357 573 free(target->ecount_diff); 574 575 if (target->table.fields != NULL) 576 free(target->table.fields); 358 577 } 359 578 … … 367 586 printf("Reading initial data...\n"); 368 587 369 if ((ret = read_data(&data _prev)) != NULL)588 if ((ret = read_data(&data)) != NULL) 370 589 goto out; 371 590 372 591 /* Compute some rubbish to have initialised values */ 373 compute_percentages(&data _prev, &data_prev);592 compute_percentages(&data, &data); 374 593 375 594 /* And paint screen until death */ 376 595 while (true) { 377 596 int c = tgetchar(UPDATE_INTERVAL); 378 if (c < 0) { 597 598 if (c < 0) { /* timeout */ 599 data_prev = data; 379 600 if ((ret = read_data(&data)) != NULL) { 380 free_data(&data );601 free_data(&data_prev); 381 602 goto out; 382 603 } 383 604 384 605 compute_percentages(&data_prev, &data); 385 sort_data(&data);386 print_data(&data);387 606 free_data(&data_prev); 388 data_prev = data; 389 390 continue; 391 } 392 607 608 c = -1; 609 } 610 611 if (screen_mode == SCREEN_HELP && c >= 0) { 612 if (c == 'h' || c == '?') 613 c = -1; 614 /* go back to table and handle the key */ 615 screen_mode = SCREEN_TABLE; 616 } 617 618 if (screen_mode == SCREEN_SORT && c >= 0) { 619 for (size_t i = 0; i < data.table.num_columns; i++) { 620 if (data.table.columns[i].key == c) { 621 sort_column = i; 622 screen_mode = SCREEN_TABLE; 623 } 624 } 625 626 c = -1; 627 } 628 393 629 switch (c) { 394 case 't': 395 print_warning("Showing task statistics"); 396 op_mode = OP_TASKS; 630 case -1: /* do nothing */ 631 break; 632 case 't': 633 op_mode = OP_TASKS; 634 break; 635 case 'i': 636 op_mode = OP_IPC; 637 break; 638 case 'e': 639 op_mode = OP_EXCS; 640 break; 641 case 's': 642 screen_mode = SCREEN_SORT; 643 break; 644 case 'r': 645 sort_reverse = -sort_reverse; 646 break; 647 case 'h': 648 case '?': 649 screen_mode = SCREEN_HELP; 650 break; 651 case 'q': 652 goto out; 653 case 'a': 654 if (op_mode == OP_EXCS) { 655 excs_all = !excs_all; 656 if (excs_all) 657 show_warning("Showing all exceptions"); 658 else 659 show_warning("Showing only hot exceptions"); 397 660 break; 398 case 'i': 399 print_warning("Showing IPC statistics"); 400 op_mode = OP_IPC; 401 break; 402 case 'e': 403 print_warning("Showing exception statistics"); 404 op_mode = OP_EXCS; 405 break; 406 case 'h': 407 print_warning("Showing help"); 408 op_mode = OP_HELP; 409 break; 410 case 'q': 411 goto out; 412 case 'a': 413 if (op_mode == OP_EXCS) { 414 excs_all = !excs_all; 415 if (excs_all) 416 print_warning("Showing all exceptions"); 417 else 418 print_warning("Showing only hot exceptions"); 419 break; 420 } 421 default: 422 print_warning("Unknown command \"%c\", use \"h\" for help", c); 423 break; 424 } 661 } 662 /* fallthrough */ 663 default: 664 show_warning("Unknown command \"%c\", use \"h\" for help", c); 665 continue; /* don't redraw */ 666 } 667 668 if ((ret = fill_table(&data)) != NULL) { 669 goto out; 670 } 671 sort_table(&data.table); 672 print_data(&data); 425 673 } 426 674 427 675 out: 428 676 screen_done(); 429 free_data(&data _prev);677 free_data(&data); 430 678 431 679 if (ret != NULL) { -
uspace/dist/src/c/demos/top/top.h
ref3da5a rb412168 51 51 52 52 typedef enum { 53 OP_TASKS, 54 OP_IPC, 55 OP_EXCS, 56 OP_HELP 57 } op_mode_t; 53 SCREEN_TABLE, 54 SCREEN_SORT, 55 SCREEN_HELP, 56 } screen_mode_t; 58 57 59 typedef enum { 60 SORT_TASK_CYCLES 61 } sort_mode_t; 62 63 extern op_mode_t op_mode; 64 extern sort_mode_t sort_mode; 65 extern bool excs_all; 58 extern screen_mode_t screen_mode; 66 59 67 60 typedef struct { … … 87 80 } perc_exc_t; 88 81 82 typedef enum { 83 FIELD_EMPTY, FIELD_UINT, FIELD_UINT_SUFFIX_BIN, FIELD_UINT_SUFFIX_DEC, 84 FIELD_PERCENT, FIELD_STRING 85 } field_type_t; 86 87 typedef struct { 88 field_type_t type; 89 union { 90 fixed_float fixed; 91 uint64_t uint; 92 const char *string; 93 }; 94 } field_t; 95 96 typedef struct { 97 const char *name; 98 char key; 99 int width; 100 } column_t; 101 102 typedef struct { 103 const char *name; 104 size_t num_columns; 105 const column_t *columns; 106 size_t num_fields; 107 field_t *fields; 108 } table_t; 109 89 110 typedef struct { 90 111 time_t hours; … … 107 128 stats_task_t *tasks; 108 129 perc_task_t *tasks_perc; 109 size_t *tasks_map;110 130 111 131 size_t threads_count; … … 122 142 uint64_t *ecycles_diff; 123 143 uint64_t *ecount_diff; 144 145 table_t table; 124 146 } data_t; 125 147 -
uspace/lib/c/generic/stats.c
ref3da5a rb412168 291 291 } 292 292 293 /** Get system uptime294 *295 * @return System uptime (in seconds).296 *297 */298 sysarg_t stats_get_uptime(void)299 {300 sysarg_t uptime;301 if (sysinfo_get_value("system.uptime", &uptime) != EOK)302 uptime = 0;303 304 return uptime;305 }306 307 293 /** Print load fixed-point value 308 294 * … … 316 302 void stats_print_load_fragment(load_t upper, unsigned int dec_length) 317 303 { 318 /* Magic value from BSD */319 load_t lower = 65536;320 321 304 /* Print the whole part */ 322 printf("%u.", upper / lower);323 324 load_t rest = (upper % lower) * 10;305 printf("%u.", upper / LOAD_UNIT); 306 307 load_t rest = (upper % LOAD_UNIT) * 10; 325 308 326 309 unsigned int i; 327 310 for (i = 0; i < dec_length; i++) { 328 printf("%u", rest / lower);329 rest = (rest % lower) * 10;311 printf("%u", rest / LOAD_UNIT); 312 rest = (rest % LOAD_UNIT) * 10; 330 313 } 331 314 } -
uspace/lib/c/generic/time.c
ref3da5a rb412168 54 54 #include <malloc.h> 55 55 56 #define ASCTIME_BUF_LEN 26 56 #define ASCTIME_BUF_LEN 26 57 58 #define HOURS_PER_DAY 24 59 #define MINS_PER_HOUR 60 60 #define SECS_PER_MIN 60 61 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 62 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) 63 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 57 64 58 65 /** Pointer to kernel shared variables with time */ … … 63 70 } *ktime = NULL; 64 71 65 /* Helper functions ***********************************************************/ 66 67 #define HOURS_PER_DAY (24) 68 #define MINS_PER_HOUR (60) 69 #define SECS_PER_MIN (60) 70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) 72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 73 74 /** 75 * Checks whether the year is a leap year. 72 static async_sess_t *clock_conn = NULL; 73 74 /** Check whether the year is a leap year. 76 75 * 77 76 * @param year Year since 1900 (e.g. for 1970, the value is 70). 77 * 78 78 * @return true if year is a leap year, false otherwise 79 */ 80 static bool _is_leap_year(time_t year) 79 * 80 */ 81 static bool is_leap_year(time_t year) 81 82 { 82 83 year += 1900; 83 84 84 85 if (year % 400 == 0) 85 86 return true; 87 86 88 if (year % 100 == 0) 87 89 return false; 90 88 91 if (year % 4 == 0) 89 92 return true; 93 90 94 return false; 91 95 } 92 96 93 /** 94 * Returns how many days there are in the given month of the given year. 97 /** How many days there are in the given month 98 * 99 * Return how many days there are in the given month of the given year. 95 100 * Note that year is only taken into account if month is February. 96 101 * 97 102 * @param year Year since 1900 (can be negative). 98 * @param mon Month of the year. 0 for January, 11 for December. 103 * @param mon Month of the year. 0 for January, 11 for December. 104 * 99 105 * @return Number of days in the specified month. 100 */ 101 static int _days_in_month(time_t year, time_t mon) 102 { 103 assert(mon >= 0 && mon <= 11); 104 105 static int month_days[] = 106 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 107 106 * 107 */ 108 static int days_in_month(time_t year, time_t mon) 109 { 110 assert(mon >= 0); 111 assert(mon <= 11); 112 113 static int month_days[] = { 114 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 115 }; 116 108 117 if (mon == 1) { 118 /* February */ 109 119 year += 1900; 110 /* february */111 return _is_leap_year(year) ? 29 : 28;112 } else {113 114 115 } 116 117 /**118 * For specified year, month and day of month, return swhich day of that year120 return is_leap_year(year) ? 29 : 28; 121 } 122 123 return month_days[mon]; 124 } 125 126 /** Which day of that year it is. 127 * 128 * For specified year, month and day of month, return which day of that year 119 129 * it is. 120 130 * 121 131 * For example, given date 2011-01-03, the corresponding expression is: 122 * _day_of_year(111, 0, 3) == 2132 * day_of_year(111, 0, 3) == 2 123 133 * 124 134 * @param year Year (year 1900 = 0, can be negative). 125 * @param mon Month (January = 0).135 * @param mon Month (January = 0). 126 136 * @param mday Day of month (First day is 1). 137 * 127 138 * @return Day of year (First day is 0). 128 */ 129 static int _day_of_year(time_t year, time_t mon, time_t mday) 130 { 131 static int mdays[] = 132 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 133 static int leap_mdays[] = 134 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; 135 136 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 137 } 138 139 /** 140 * Integer division that rounds to negative infinity. 141 * Used by some functions in this file. 139 * 140 */ 141 static int day_of_year(time_t year, time_t mon, time_t mday) 142 { 143 static int mdays[] = { 144 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 145 }; 146 147 static int leap_mdays[] = { 148 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 149 }; 150 151 return (is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 152 } 153 154 /** Integer division that rounds to negative infinity. 155 * 156 * Used by some functions in this module. 142 157 * 143 158 * @param op1 Dividend. 144 159 * @param op2 Divisor. 160 * 145 161 * @return Rounded quotient. 146 */ 147 static time_t _floor_div(time_t op1, time_t op2) 148 { 149 if (op1 >= 0 || op1 % op2 == 0) { 162 * 163 */ 164 static time_t floor_div(time_t op1, time_t op2) 165 { 166 if ((op1 >= 0) || (op1 % op2 == 0)) 150 167 return op1 / op2; 151 } else { 152 return op1 / op2 - 1; 153 } 154 } 155 156 /** 157 * Modulo that rounds to negative infinity. 158 * Used by some functions in this file. 168 169 return op1 / op2 - 1; 170 } 171 172 /** Modulo that rounds to negative infinity. 173 * 174 * Used by some functions in this module. 159 175 * 160 176 * @param op1 Dividend. 161 177 * @param op2 Divisor. 178 * 162 179 * @return Remainder. 163 */ 164 static time_t _floor_mod(time_t op1, time_t op2) 165 { 166 int div = _floor_div(op1, op2); 167 168 /* (a / b) * b + a % b == a */ 169 /* thus, a % b == a - (a / b) * b */ 170 171 int result = op1 - div * op2; 172 173 /* Some paranoid checking to ensure I didn't make a mistake here. */ 180 * 181 */ 182 static time_t floor_mod(time_t op1, time_t op2) 183 { 184 time_t div = floor_div(op1, op2); 185 186 /* 187 * (a / b) * b + a % b == a 188 * Thus: a % b == a - (a / b) * b 189 */ 190 191 time_t result = op1 - div * op2; 192 193 /* Some paranoid checking to ensure there is mistake here. */ 174 194 assert(result >= 0); 175 195 assert(result < op2); … … 179 199 } 180 200 181 /** 182 * Number of days since the Epoch.201 /** Number of days since the Epoch. 202 * 183 203 * Epoch is 1970-01-01, which is also equal to day 0. 184 204 * 185 205 * @param year Year (year 1900 = 0, may be negative). 186 * @param mon Month (January = 0).206 * @param mon Month (January = 0). 187 207 * @param mday Day of month (first day = 1). 208 * 188 209 * @return Number of days since the Epoch. 189 */ 190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday) 191 { 192 return (year - 70) * 365 + _floor_div(year - 69, 4) - 193 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) + 194 _day_of_year(year, mon, mday); 195 } 196 197 /** 198 * Seconds since the Epoch. see also _days_since_epoch(). 199 * 210 * 211 */ 212 static time_t days_since_epoch(time_t year, time_t mon, time_t mday) 213 { 214 return (year - 70) * 365 + floor_div(year - 69, 4) - 215 floor_div(year - 1, 100) + floor_div(year + 299, 400) + 216 day_of_year(year, mon, mday); 217 } 218 219 /** Seconds since the Epoch. 220 * 221 * See also days_since_epoch(). 222 * 200 223 * @param tm Normalized broken-down time. 224 * 201 225 * @return Number of seconds since the epoch, not counting leap seconds. 202 */ 203 static time_t _secs_since_epoch(const struct tm *tm) 204 { 205 return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) * 226 * 227 */ 228 static time_t secs_since_epoch(const struct tm *tm) 229 { 230 return days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) * 206 231 SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR + 207 232 tm->tm_min * SECS_PER_MIN + tm->tm_sec; 208 233 } 209 234 210 /** 211 * Which day of week the specified date is. 212 * 235 /** Which day of week the specified date is. 236 * 213 237 * @param year Year (year 1900 = 0). 214 * @param mon Month (January = 0).238 * @param mon Month (January = 0). 215 239 * @param mday Day of month (first = 1). 240 * 216 241 * @return Day of week (Sunday = 0). 217 */ 218 static int _day_of_week(time_t year, time_t mon, time_t mday) 242 * 243 */ 244 static time_t day_of_week(time_t year, time_t mon, time_t mday) 219 245 { 220 246 /* 1970-01-01 is Thursday */ 221 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);222 } 223 224 /** 225 * Normalizes the broken-down time and optionally adds specified amount of226 * seconds.227 * 228 * @param tm Broken-down time to normalize.247 return floor_mod(days_since_epoch(year, mon, mday) + 4, 7); 248 } 249 250 /** Normalize the broken-down time. 251 * 252 * Optionally add specified amount of seconds. 253 * 254 * @param tm Broken-down time to normalize. 229 255 * @param sec_add Seconds to add. 256 * 230 257 * @return 0 on success, -1 on overflow 231 */ 232 static int _normalize_time(struct tm *tm, time_t sec_add) 258 * 259 */ 260 static int normalize_time(struct tm *tm, time_t sec_add) 233 261 { 234 262 // TODO: DST correction 235 263 236 264 /* Set initial values. */ 237 265 time_t sec = tm->tm_sec + sec_add; … … 241 269 time_t mon = tm->tm_mon; 242 270 time_t year = tm->tm_year; 243 271 244 272 /* Adjust time. */ 245 min += _floor_div(sec, SECS_PER_MIN);246 sec = _floor_mod(sec, SECS_PER_MIN);247 hour += _floor_div(min, MINS_PER_HOUR);248 min = _floor_mod(min, MINS_PER_HOUR);249 day += _floor_div(hour, HOURS_PER_DAY);250 hour = _floor_mod(hour, HOURS_PER_DAY);251 273 min += floor_div(sec, SECS_PER_MIN); 274 sec = floor_mod(sec, SECS_PER_MIN); 275 hour += floor_div(min, MINS_PER_HOUR); 276 min = floor_mod(min, MINS_PER_HOUR); 277 day += floor_div(hour, HOURS_PER_DAY); 278 hour = floor_mod(hour, HOURS_PER_DAY); 279 252 280 /* Adjust month. */ 253 year += _floor_div(mon, 12);254 mon = _floor_mod(mon, 12);255 281 year += floor_div(mon, 12); 282 mon = floor_mod(mon, 12); 283 256 284 /* Now the difficult part - days of month. */ 257 285 258 286 /* First, deal with whole cycles of 400 years = 146097 days. */ 259 year += _floor_div(day, 146097) * 400;260 day = _floor_mod(day, 146097);287 year += floor_div(day, 146097) * 400; 288 day = floor_mod(day, 146097); 261 289 262 290 /* Then, go in one year steps. */ … … 264 292 /* January and February. */ 265 293 while (day > 365) { 266 day -= _is_leap_year(year) ? 366 : 365;294 day -= is_leap_year(year) ? 366 : 365; 267 295 year++; 268 296 } … … 270 298 /* Rest of the year. */ 271 299 while (day > 365) { 272 day -= _is_leap_year(year + 1) ? 366 : 365;300 day -= is_leap_year(year + 1) ? 366 : 365; 273 301 year++; 274 302 } … … 276 304 277 305 /* Finally, finish it off month per month. */ 278 while (day >= _days_in_month(year, mon)) {279 day -= _days_in_month(year, mon);306 while (day >= days_in_month(year, mon)) { 307 day -= days_in_month(year, mon); 280 308 mon++; 309 281 310 if (mon >= 12) { 282 311 mon -= 12; … … 286 315 287 316 /* Calculate the remaining two fields. */ 288 tm->tm_yday = _day_of_year(year, mon, day + 1);289 tm->tm_wday = _day_of_week(year, mon, day + 1);317 tm->tm_yday = day_of_year(year, mon, day + 1); 318 tm->tm_wday = day_of_week(year, mon, day + 1); 290 319 291 320 /* And put the values back to the struct. */ … … 296 325 tm->tm_mon = (int) mon; 297 326 298 /* Casts to work around libcbrain-damage. */299 if (year > ((int) INT_MAX) || year < ((int)INT_MIN)) {300 tm->tm_year = (year < 0) ? ((int) INT_MIN) : ((int)INT_MAX);327 /* Casts to work around POSIX brain-damage. */ 328 if (year > ((int) INT_MAX) || year < ((int) INT_MIN)) { 329 tm->tm_year = (year < 0) ? ((int) INT_MIN) : ((int) INT_MAX); 301 330 return -1; 302 331 } … … 306 335 } 307 336 308 /** 309 * Which day the week-based year starts on, relative to the first calendar day. 310 * E.g. if the year starts on December 31st, the return value is -1. 337 /** Which day the week-based year starts on. 338 * 339 * Relative to the first calendar day. E.g. if the year starts 340 * on December 31st, the return value is -1. 311 341 * 312 342 * @param Year since 1900. 343 * 313 344 * @return Offset of week-based year relative to calendar year. 314 */ 315 static int _wbyear_offset(int year) 316 { 317 int start_wday = _day_of_week(year, 0, 1); 318 return _floor_mod(4 - start_wday, 7) - 3; 319 } 320 321 /** 322 * Returns week-based year of the specified time. 345 * 346 */ 347 static int wbyear_offset(int year) 348 { 349 int start_wday = day_of_week(year, 0, 1); 350 351 return floor_mod(4 - start_wday, 7) - 3; 352 } 353 354 /** Week-based year of the specified time. 323 355 * 324 356 * @param tm Normalized broken-down time. 357 * 325 358 * @return Week-based year. 326 */ 327 static int _wbyear(const struct tm *tm) 328 { 329 int day = tm->tm_yday - _wbyear_offset(tm->tm_year); 359 * 360 */ 361 static int wbyear(const struct tm *tm) 362 { 363 int day = tm->tm_yday - wbyear_offset(tm->tm_year); 364 330 365 if (day < 0) { 331 366 /* Last week of previous year. */ 332 367 return tm->tm_year - 1; 333 368 } 334 if (day > 364 + _is_leap_year(tm->tm_year)) { 369 370 if (day > 364 + is_leap_year(tm->tm_year)) { 335 371 /* First week of next year. */ 336 372 return tm->tm_year + 1; 337 373 } 374 338 375 /* All the other days are in the calendar year. */ 339 376 return tm->tm_year; 340 377 } 341 378 342 /** 343 * Week number of the year, assuming weeks start on sunday.379 /** Week number of the year (assuming weeks start on Sunday). 380 * 344 381 * The first Sunday of January is the first day of week 1; 345 382 * days in the new year before this are in week 0. 346 383 * 347 384 * @param tm Normalized broken-down time. 385 * 348 386 * @return The week number (0 - 53). 349 */ 350 static int _sun_week_number(const struct tm *tm) 351 { 352 int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7; 387 * 388 */ 389 static int sun_week_number(const struct tm *tm) 390 { 391 int first_day = (7 - day_of_week(tm->tm_year, 0, 1)) % 7; 392 353 393 return (tm->tm_yday - first_day + 7) / 7; 354 394 } 355 395 356 /** 357 * Week number of the year, assuming weeks start on monday. 358 * If the week containing January 1st has four or more days in the new year, 359 * then it is considered week 1. Otherwise, it is the last week of the previous 360 * year, and the next week is week 1. Both January 4th and the first Thursday 396 /** Week number of the year (assuming weeks start on Monday). 397 * 398 * If the week containing January 1st has four or more days 399 * in the new year, then it is considered week 1. Otherwise, 400 * it is the last week of the previous year, and the next week 401 * is week 1. Both January 4th and the first Thursday 361 402 * of January are always in week 1. 362 403 * 363 404 * @param tm Normalized broken-down time. 405 * 364 406 * @return The week number (1 - 53). 365 */ 366 static int _iso_week_number(const struct tm *tm) 367 { 368 int day = tm->tm_yday - _wbyear_offset(tm->tm_year); 407 * 408 */ 409 static int iso_week_number(const struct tm *tm) 410 { 411 int day = tm->tm_yday - wbyear_offset(tm->tm_year); 412 369 413 if (day < 0) { 370 414 /* Last week of previous year. */ 371 415 return 53; 372 416 } 373 if (day > 364 + _is_leap_year(tm->tm_year)) { 417 418 if (day > 364 + is_leap_year(tm->tm_year)) { 374 419 /* First week of next year. */ 375 420 return 1; 376 421 } 422 377 423 /* All the other days give correct answer. */ 378 424 return (day / 7 + 1); 379 425 } 380 426 381 /** 382 * Week number of the year, assuming weeks start on monday.427 /** Week number of the year (assuming weeks start on Monday). 428 * 383 429 * The first Monday of January is the first day of week 1; 384 * days in the new year before this are in week 0. 430 * days in the new year before this are in week 0. 385 431 * 386 432 * @param tm Normalized broken-down time. 433 * 387 434 * @return The week number (0 - 53). 388 */ 389 static int _mon_week_number(const struct tm *tm) 390 { 391 int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7; 435 * 436 */ 437 static int mon_week_number(const struct tm *tm) 438 { 439 int first_day = (1 - day_of_week(tm->tm_year, 0, 1)) % 7; 440 392 441 return (tm->tm_yday - first_day + 7) / 7; 393 442 } 394 395 /******************************************************************************/396 397 443 398 444 /** Add microseconds to given timeval. … … 468 514 } 469 515 470 /** Get time of day 516 /** Get time of day. 471 517 * 472 518 * The time variables are memory mapped (read-only) from kernel which … … 482 528 * 483 529 */ 484 int gettimeofday(struct timeval *tv, struct timezone *tz) 485 { 486 int rc; 487 struct tm t; 488 category_id_t cat_id; 489 size_t svc_cnt; 490 service_id_t *svc_ids = NULL; 491 service_id_t svc_id; 492 char *svc_name = NULL; 493 494 static async_sess_t *clock_conn = NULL; 495 530 void gettimeofday(struct timeval *tv, struct timezone *tz) 531 { 496 532 if (tz) { 497 533 tz->tz_minuteswest = 0; 498 534 tz->tz_dsttime = DST_NONE; 499 535 } 500 536 501 537 if (clock_conn == NULL) { 502 rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING); 538 category_id_t cat_id; 539 int rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING); 503 540 if (rc != EOK) 504 goto ret_uptime; 505 541 goto fallback; 542 543 service_id_t *svc_ids; 544 size_t svc_cnt; 506 545 rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt); 507 546 if (rc != EOK) 508 goto ret_uptime;509 547 goto fallback; 548 510 549 if (svc_cnt == 0) 511 goto ret_uptime; 512 550 goto fallback; 551 552 char *svc_name; 513 553 rc = loc_service_get_name(svc_ids[0], &svc_name); 554 free(svc_ids); 514 555 if (rc != EOK) 515 goto ret_uptime; 516 556 goto fallback; 557 558 service_id_t svc_id; 517 559 rc = loc_service_get_id(svc_name, &svc_id, 0); 560 free(svc_name); 518 561 if (rc != EOK) 519 goto ret_uptime;520 562 goto fallback; 563 521 564 clock_conn = loc_service_connect(EXCHANGE_SERIALIZE, 522 565 svc_id, IPC_FLAG_BLOCKING); 523 566 if (!clock_conn) 524 goto ret_uptime; 525 } 526 527 rc = clock_dev_time_get(clock_conn, &t); 567 goto fallback; 568 } 569 570 struct tm time; 571 int rc = clock_dev_time_get(clock_conn, &time); 528 572 if (rc != EOK) 529 goto ret_uptime;530 573 goto fallback; 574 531 575 tv->tv_usec = 0; 532 tv->tv_sec = mktime(&t); 533 534 free(svc_name); 535 free(svc_ids); 536 537 return EOK; 538 539 ret_uptime: 540 541 free(svc_name); 542 free(svc_ids); 543 544 return getuptime(tv); 545 } 546 547 int getuptime(struct timeval *tv) 576 tv->tv_sec = mktime(&time); 577 578 return; 579 580 fallback: 581 getuptime(tv); 582 } 583 584 void getuptime(struct timeval *tv) 548 585 { 549 586 if (ktime == NULL) { … … 552 589 if (rc != EOK) { 553 590 errno = rc; 554 return -1;591 goto fallback; 555 592 } 556 593 … … 561 598 as_area_destroy(addr); 562 599 errno = rc; 563 return -1;600 goto fallback; 564 601 } 565 602 … … 580 617 } else 581 618 tv->tv_sec = s1; 582 583 return 0; 619 620 return; 621 622 fallback: 623 tv->tv_sec = 0; 624 tv->tv_usec = 0; 584 625 } 585 626 … … 587 628 { 588 629 struct timeval tv; 589 if (gettimeofday(&tv, NULL)) 590 return (time_t) -1; 630 gettimeofday(&tv, NULL); 591 631 592 632 if (tloc) … … 631 671 } 632 672 633 /** 634 * This function first normalizes the provided broken-down time 635 * (moves all values to their proper bounds) and then tries to 636 * calculate the appropriate time_t representation. 673 /** Get time from broken-down time. 674 * 675 * First normalize the provided broken-down time 676 * (moves all values to their proper bounds) and 677 * then try to calculate the appropriate time_t 678 * representation. 637 679 * 638 680 * @param tm Broken-down time. 639 * @return time_t representation of the time, undefined value on overflow. 681 * 682 * @return time_t representation of the time. 683 * @return Undefined value on overflow. 684 * 640 685 */ 641 686 time_t mktime(struct tm *tm) … … 643 688 // TODO: take DST flag into account 644 689 // TODO: detect overflow 645 646 _normalize_time(tm, 0); 647 return _secs_since_epoch(tm); 648 } 649 650 /** 651 * Convert time and date to a string, based on a specified format and 652 * current locale. 653 * 654 * @param s Buffer to write string to. 690 691 normalize_time(tm, 0); 692 return secs_since_epoch(tm); 693 } 694 695 /* 696 * FIXME: This requires POSIX-correct snprintf. 697 * Otherwise it won't work with non-ASCII chars. 698 */ 699 #define APPEND(...) \ 700 { \ 701 consumed = snprintf(ptr, remaining, __VA_ARGS__); \ 702 if (consumed >= remaining) \ 703 return 0; \ 704 \ 705 ptr += consumed; \ 706 remaining -= consumed; \ 707 } 708 709 #define RECURSE(fmt) \ 710 { \ 711 consumed = strftime(ptr, remaining, fmt, tm); \ 712 if (consumed == 0) \ 713 return 0; \ 714 \ 715 ptr += consumed; \ 716 remaining -= consumed; \ 717 } 718 719 #define TO_12H(hour) \ 720 (((hour) > 12) ? ((hour) - 12) : \ 721 (((hour) == 0) ? 12 : (hour))) 722 723 /** Convert time and date to a string. 724 * 725 * @param s Buffer to write string to. 655 726 * @param maxsize Size of the buffer. 656 * @param format Format of the output. 657 * @param tm Broken-down time to format. 727 * @param format Format of the output. 728 * @param tm Broken-down time to format. 729 * 658 730 * @return Number of bytes written. 731 * 659 732 */ 660 733 size_t strftime(char *restrict s, size_t maxsize, … … 664 737 assert(format != NULL); 665 738 assert(tm != NULL); 666 739 667 740 // TODO: use locale 741 668 742 static const char *wday_abbr[] = { 669 743 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 670 744 }; 745 671 746 static const char *wday[] = { 672 747 "Sunday", "Monday", "Tuesday", "Wednesday", 673 748 "Thursday", "Friday", "Saturday" 674 749 }; 750 675 751 static const char *mon_abbr[] = { 676 752 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 677 753 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 678 754 }; 755 679 756 static const char *mon[] = { 680 757 "January", "February", "March", "April", "May", "June", "July", … … 682 759 }; 683 760 684 if (maxsize < 1) {761 if (maxsize < 1) 685 762 return 0; 686 }687 763 688 764 char *ptr = s; … … 690 766 size_t remaining = maxsize; 691 767 692 #define append(...) { \693 /* FIXME: this requires POSIX-correct snprintf */ \694 /* otherwise it won't work with non-ascii chars */ \695 consumed = snprintf(ptr, remaining, __VA_ARGS__); \696 if (consumed >= remaining) { \697 return 0; \698 } \699 ptr += consumed; \700 remaining -= consumed; \701 }702 703 #define recurse(fmt) { \704 consumed = strftime(ptr, remaining, fmt, tm); \705 if (consumed == 0) { \706 return 0; \707 } \708 ptr += consumed; \709 remaining -= consumed; \710 }711 712 #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \713 (((hour) == 0) ? 12 : (hour)))714 715 768 while (*format != '\0') { 716 769 if (*format != '%') { 717 append("%c", *format);770 APPEND("%c", *format); 718 771 format++; 719 772 continue; … … 721 774 722 775 format++; 723 if ( *format == '0' || *format == '+') {776 if ((*format == '0') || (*format == '+')) { 724 777 // TODO: padding 725 778 format++; 726 779 } 780 727 781 while (isdigit(*format)) { 728 782 // TODO: padding 729 783 format++; 730 784 } 731 if (*format == 'O' || *format == 'E') { 785 786 if ((*format == 'O') || (*format == 'E')) { 732 787 // TODO: locale's alternative format 733 788 format++; … … 736 791 switch (*format) { 737 792 case 'a': 738 append("%s", wday_abbr[tm->tm_wday]); break; 793 APPEND("%s", wday_abbr[tm->tm_wday]); 794 break; 739 795 case 'A': 740 append("%s", wday[tm->tm_wday]); break; 796 APPEND("%s", wday[tm->tm_wday]); 797 break; 741 798 case 'b': 742 append("%s", mon_abbr[tm->tm_mon]); break; 799 APPEND("%s", mon_abbr[tm->tm_mon]); 800 break; 743 801 case 'B': 744 append("%s", mon[tm->tm_mon]); break; 802 APPEND("%s", mon[tm->tm_mon]); 803 break; 745 804 case 'c': 746 805 // TODO: locale-specific datetime format 747 recurse("%Y-%m-%d %H:%M:%S"); break; 806 RECURSE("%Y-%m-%d %H:%M:%S"); 807 break; 748 808 case 'C': 749 append("%02d", (1900 + tm->tm_year) / 100); break; 809 APPEND("%02d", (1900 + tm->tm_year) / 100); 810 break; 750 811 case 'd': 751 append("%02d", tm->tm_mday); break; 812 APPEND("%02d", tm->tm_mday); 813 break; 752 814 case 'D': 753 recurse("%m/%d/%y"); break; 815 RECURSE("%m/%d/%y"); 816 break; 754 817 case 'e': 755 append("%2d", tm->tm_mday); break; 818 APPEND("%2d", tm->tm_mday); 819 break; 756 820 case 'F': 757 recurse("%+4Y-%m-%d"); break; 821 RECURSE("%+4Y-%m-%d"); 822 break; 758 823 case 'g': 759 append("%02d", _wbyear(tm) % 100); break; 824 APPEND("%02d", wbyear(tm) % 100); 825 break; 760 826 case 'G': 761 append("%d", _wbyear(tm)); break; 827 APPEND("%d", wbyear(tm)); 828 break; 762 829 case 'h': 763 recurse("%b"); break; 830 RECURSE("%b"); 831 break; 764 832 case 'H': 765 append("%02d", tm->tm_hour); break; 833 APPEND("%02d", tm->tm_hour); 834 break; 766 835 case 'I': 767 append("%02d", TO_12H(tm->tm_hour)); break; 836 APPEND("%02d", TO_12H(tm->tm_hour)); 837 break; 768 838 case 'j': 769 append("%03d", tm->tm_yday); break; 839 APPEND("%03d", tm->tm_yday); 840 break; 770 841 case 'k': 771 append("%2d", tm->tm_hour); break; 842 APPEND("%2d", tm->tm_hour); 843 break; 772 844 case 'l': 773 append("%2d", TO_12H(tm->tm_hour)); break; 845 APPEND("%2d", TO_12H(tm->tm_hour)); 846 break; 774 847 case 'm': 775 append("%02d", tm->tm_mon); break; 848 APPEND("%02d", tm->tm_mon); 849 break; 776 850 case 'M': 777 append("%02d", tm->tm_min); break; 851 APPEND("%02d", tm->tm_min); 852 break; 778 853 case 'n': 779 append("\n"); break; 854 APPEND("\n"); 855 break; 780 856 case 'p': 781 append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break; 857 APPEND("%s", tm->tm_hour < 12 ? "AM" : "PM"); 858 break; 782 859 case 'P': 783 append("%s", tm->tm_hour < 12 ? "am" : "PM"); break; 860 APPEND("%s", tm->tm_hour < 12 ? "am" : "PM"); 861 break; 784 862 case 'r': 785 recurse("%I:%M:%S %p"); break; 863 RECURSE("%I:%M:%S %p"); 864 break; 786 865 case 'R': 787 recurse("%H:%M"); break; 866 RECURSE("%H:%M"); 867 break; 788 868 case 's': 789 append("%ld", _secs_since_epoch(tm)); break; 869 APPEND("%ld", secs_since_epoch(tm)); 870 break; 790 871 case 'S': 791 append("%02d", tm->tm_sec); break; 872 APPEND("%02d", tm->tm_sec); 873 break; 792 874 case 't': 793 append("\t"); break; 875 APPEND("\t"); 876 break; 794 877 case 'T': 795 recurse("%H:%M:%S"); break; 878 RECURSE("%H:%M:%S"); 879 break; 796 880 case 'u': 797 append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);881 APPEND("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); 798 882 break; 799 883 case 'U': 800 append("%02d", _sun_week_number(tm)); break; 884 APPEND("%02d", sun_week_number(tm)); 885 break; 801 886 case 'V': 802 append("%02d", _iso_week_number(tm)); break; 887 APPEND("%02d", iso_week_number(tm)); 888 break; 803 889 case 'w': 804 append("%d", tm->tm_wday); break; 890 APPEND("%d", tm->tm_wday); 891 break; 805 892 case 'W': 806 append("%02d", _mon_week_number(tm)); break; 893 APPEND("%02d", mon_week_number(tm)); 894 break; 807 895 case 'x': 808 896 // TODO: locale-specific date format 809 recurse("%Y-%m-%d"); break; 897 RECURSE("%Y-%m-%d"); 898 break; 810 899 case 'X': 811 900 // TODO: locale-specific time format 812 recurse("%H:%M:%S"); break; 901 RECURSE("%H:%M:%S"); 902 break; 813 903 case 'y': 814 append("%02d", tm->tm_year % 100); break; 904 APPEND("%02d", tm->tm_year % 100); 905 break; 815 906 case 'Y': 816 append("%d", 1900 + tm->tm_year); break; 907 APPEND("%d", 1900 + tm->tm_year); 908 break; 817 909 case 'z': 818 910 // TODO: timezone … … 822 914 break; 823 915 case '%': 824 append("%%");916 APPEND("%%"); 825 917 break; 826 918 default: 827 919 /* Invalid specifier, print verbatim. */ 828 while (*format != '%') {920 while (*format != '%') 829 921 format--; 830 }831 append("%%");922 923 APPEND("%%"); 832 924 break; 833 925 } 926 834 927 format++; 835 928 } 836 929 837 #undef append838 #undef recurse839 840 930 return maxsize - remaining; 841 931 } 842 932 843 844 /** Converts a time value to a broken-down UTC time 845 * 846 * @param time Time to convert847 * @param result Structure to store the result to848 * 849 * @return EOK or a negative error code933 /** Convert a time value to a broken-down UTC time/ 934 * 935 * @param time Time to convert 936 * @param result Structure to store the result to 937 * 938 * @return EOK or a negative error code 939 * 850 940 */ 851 941 int time_utc2tm(const time_t time, struct tm *restrict result) 852 942 { 853 943 assert(result != NULL); 854 944 855 945 /* Set result to epoch. */ 856 946 result->tm_sec = 0; … … 860 950 result->tm_mon = 0; 861 951 result->tm_year = 70; /* 1970 */ 862 863 if ( _normalize_time(result, time) == -1)952 953 if (normalize_time(result, time) == -1) 864 954 return EOVERFLOW; 865 955 866 956 return EOK; 867 957 } 868 958 869 /** Converts a time value to a null terminated string of the form 870 * "Wed Jun 30 21:49:08 1993\n" expressed in UTC. 871 * 872 * @param time Time to convert. 873 * @param buf Buffer to store the string to, must be at least 874 * ASCTIME_BUF_LEN bytes long. 875 * 876 * @return EOK or a negative error code. 959 /** Convert a time value to a NULL-terminated string. 960 * 961 * The format is "Wed Jun 30 21:49:08 1993\n" expressed in UTC. 962 * 963 * @param time Time to convert. 964 * @param buf Buffer to store the string to, must be at least 965 * ASCTIME_BUF_LEN bytes long. 966 * 967 * @return EOK or a negative error code. 968 * 877 969 */ 878 970 int time_utc2str(const time_t time, char *restrict buf) 879 971 { 880 struct tm t; 881 int r; 882 883 if ((r = time_utc2tm(time, &t)) != EOK) 884 return r; 885 886 time_tm2str(&t, buf); 972 struct tm tm; 973 int ret = time_utc2tm(time, &tm); 974 if (ret != EOK) 975 return ret; 976 977 time_tm2str(&tm, buf); 887 978 return EOK; 888 979 } 889 980 890 891 /** 892 * Converts broken-down time to a string in format 893 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 981 /** Convert broken-down time to a NULL-terminated string. 982 * 983 * The format is "Sun Jan 1 00:00:00 1970\n". (Obsolete) 894 984 * 895 985 * @param timeptr Broken-down time structure. 896 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN 897 * bytes long. 986 * @param buf Buffer to store string to, must be at least 987 * ASCTIME_BUF_LEN bytes long. 988 * 898 989 */ 899 990 void time_tm2str(const struct tm *restrict timeptr, char *restrict buf) … … 901 992 assert(timeptr != NULL); 902 993 assert(buf != NULL); 903 994 904 995 static const char *wday[] = { 905 996 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 906 997 }; 998 907 999 static const char *mon[] = { 908 1000 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 909 1001 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 910 1002 }; 911 1003 912 1004 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n", 913 1005 wday[timeptr->tm_wday], … … 918 1010 } 919 1011 920 /** 921 * Converts a time value to a broken-down local time, expressed relative 922 * to the user's specified timezone. 923 * 924 * @param timer Time to convert. 925 * @param result Structure to store the result to. 926 * 927 * @return EOK on success or a negative error code. 1012 /** Converts a time value to a broken-down local time. 1013 * 1014 * Time is expressed relative to the user's specified timezone. 1015 * 1016 * @param timer Time to convert. 1017 * @param result Structure to store the result to. 1018 * 1019 * @return EOK on success or a negative error code. 1020 * 928 1021 */ 929 1022 int time_local2tm(const time_t time, struct tm *restrict result) 930 1023 { 931 // TODO: deal with timezone932 // currently assumes system and all times are in GMT933 1024 // TODO: Deal with timezones. 1025 // Currently assumes system and all times are in UTC 1026 934 1027 /* Set result to epoch. */ 935 1028 result->tm_sec = 0; … … 939 1032 result->tm_mon = 0; 940 1033 result->tm_year = 70; /* 1970 */ 941 942 if ( _normalize_time(result, time) == -1)1034 1035 if (normalize_time(result, time) == -1) 943 1036 return EOVERFLOW; 944 1037 945 1038 return EOK; 946 1039 } 947 1040 948 /** 949 * Converts the calendar time to a null terminated string950 * of the form"Wed Jun 30 21:49:08 1993\n" expressed relative to the1041 /** Convert the calendar time to a NULL-terminated string. 1042 * 1043 * The format is "Wed Jun 30 21:49:08 1993\n" expressed relative to the 951 1044 * user's specified timezone. 952 * 953 * @param timer Time to convert. 954 * @param buf Buffer to store the string to. Must be at least 955 * ASCTIME_BUF_LEN bytes long. 956 * 957 * @return EOK on success or a negative error code. 1045 * 1046 * @param timer Time to convert. 1047 * @param buf Buffer to store the string to. Must be at least 1048 * ASCTIME_BUF_LEN bytes long. 1049 * 1050 * @return EOK on success or a negative error code. 1051 * 958 1052 */ 959 1053 int time_local2str(const time_t time, char *buf) 960 1054 { 961 1055 struct tm loctime; 962 int r; 963 964 if ((r = time_local2tm(time, &loctime)) != EOK) 965 return r; 966 1056 int ret = time_local2tm(time, &loctime); 1057 if (ret != EOK) 1058 return ret; 1059 967 1060 time_tm2str(&loctime, buf); 968 969 1061 return EOK; 970 1062 } 971 1063 972 /** 973 * Calculate the difference between two times, in seconds. 974 * 1064 /** Calculate the difference between two times, in seconds. 1065 * 975 1066 * @param time1 First time. 976 1067 * @param time0 Second time. 977 * @return Time in seconds. 1068 * 1069 * @return Time difference in seconds. 1070 * 978 1071 */ 979 1072 double difftime(time_t time1, time_t time0) -
uspace/lib/c/include/fourcc.h
ref3da5a rb412168 38 38 #include <libarch/common.h> 39 39 40 typedef uint32_t fourcc_t; 41 40 42 #define FOURCC(a, b, c, d) \ 41 43 (((UINT32_T) (a)) | (((UINT32_T) (b)) << 8) | \ -
uspace/lib/c/include/stats.h
ref3da5a rb412168 43 43 #include <abi/sysinfo.h> 44 44 45 #define LOAD_UNIT 65536 46 45 47 extern stats_cpu_t *stats_get_cpus(size_t *); 46 48 extern stats_physmem_t *stats_get_physmem(void); 47 49 extern load_t *stats_get_load(size_t *); 48 extern sysarg_t stats_get_uptime(void);49 50 50 51 extern stats_task_t *stats_get_tasks(size_t *); -
uspace/lib/c/include/stddef.h
ref3da5a rb412168 42 42 #endif 43 43 44 #define offsetof(type,member) ((size_t) &(((type *) 0)->member)) 44 45 45 46 #endif -
uspace/lib/c/include/sys/time.h
ref3da5a rb412168 40 40 #include <sys/types.h> 41 41 42 #define DST_NONE 043 #define ASCTIME_BUF_LEN 2642 #define DST_NONE 0 43 #define ASCTIME_BUF_LEN 26 44 44 45 45 typedef long time_t; … … 50 50 51 51 struct tm { 52 int tm_sec; 53 int tm_min; 54 int tm_hour; 55 int tm_mday; 56 int tm_mon; 57 int tm_year; 58 int tm_wday; 59 int tm_yday; 60 int tm_isdst; 52 int tm_sec; /* Seconds [0,60]. */ 53 int tm_min; /* Minutes [0,59]. */ 54 int tm_hour; /* Hour [0,23]. */ 55 int tm_mday; /* Day of month [1,31]. */ 56 int tm_mon; /* Month of year [0,11]. */ 57 int tm_year; /* Years since 1900. */ 58 int tm_wday; /* Day of week [0,6] (Sunday = 0). */ 59 int tm_yday; /* Day of year [0,365]. */ 60 int tm_isdst; /* Daylight Savings flag. */ 61 61 }; 62 62 … … 71 71 }; 72 72 73 extern void tv_add(struct timeval * tv, suseconds_t usecs);74 extern suseconds_t tv_sub(struct timeval * tv1, struct timeval *tv2);75 extern int tv_gt(struct timeval * tv1, struct timeval *tv2);76 extern int tv_gteq(struct timeval * tv1, struct timeval *tv2);77 extern int gettimeofday(struct timeval *tv, struct timezone *tz);78 extern int getuptime(struct timeval *tv);73 extern void tv_add(struct timeval *, suseconds_t); 74 extern suseconds_t tv_sub(struct timeval *, struct timeval *); 75 extern int tv_gt(struct timeval *, struct timeval *); 76 extern int tv_gteq(struct timeval *, struct timeval *); 77 extern void gettimeofday(struct timeval *, struct timezone *); 78 extern void getuptime(struct timeval *); 79 79 80 80 extern void udelay(useconds_t); 81 81 82 extern time_t mktime(struct tm * tm);83 extern int time_utc2tm(const time_t time, struct tm *result);84 extern int time_utc2str(const time_t time, char *buf);85 extern void time_tm2str(const struct tm * timeptr, char *buf);86 extern int time_local2tm(const time_t time, struct tm *result);87 extern int time_local2str(const time_t time, char *buf);88 extern double difftime(time_t time1, time_t time0);89 extern size_t strftime(char *restrict s, size_t maxsize,90 const char *restrict format, const struct tm *restrict tm);82 extern time_t mktime(struct tm *); 83 extern int time_utc2tm(const time_t, struct tm *); 84 extern int time_utc2str(const time_t, char *); 85 extern void time_tm2str(const struct tm *, char *); 86 extern int time_local2tm(const time_t, struct tm *); 87 extern int time_local2str(const time_t, char *); 88 extern double difftime(time_t, time_t); 89 extern size_t strftime(char *restrict, size_t, const char *restrict, 90 const struct tm *restrict); 91 91 92 92 #endif -
uspace/lib/draw/Makefile
ref3da5a rb412168 31 31 SLIBRARY = libdraw.so.0.0 32 32 LSONAME = libdraw.so0 33 EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX) 33 EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX) -I$(LIBCOMPRESS_PREFIX) 34 34 35 35 SOURCES = \ 36 36 codec/tga.c \ 37 codec/tga.gz.c \ 38 codec/webp.c \ 37 39 cursor/embedded.c \ 38 40 font/embedded.c \ -
uspace/lib/draw/codec/tga.c
ref3da5a rb412168 110 110 * @return True on succesful decoding. 111 111 * @return False on failure. 112 * 112 113 */ 113 114 static bool decode_tga_header(void *data, size_t size, tga_t *tga) … … 174 175 * @return Newly allocated surface with the decoded content. 175 176 * @return NULL on error or unsupported format. 177 * 176 178 */ 177 179 surface_t *decode_tga(void *data, size_t size, surface_flags_t flags) … … 264 266 * @return True on succesful encoding. 265 267 * @return False on failure. 268 * 266 269 */ 267 270 bool encode_tga(surface_t *surface, void **pdata, size_t *psize) -
uspace/lib/trackmod/Makefile
ref3da5a rb412168 32 32 SOURCES = \ 33 33 protracker.c \ 34 trackmod.c 34 trackmod.c \ 35 xm.c 35 36 36 37 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/trackmod/protracker.c
ref3da5a rb412168 113 113 } 114 114 115 116 /** Decode pattern cell. 117 * 118 * @param pattern Pattern 119 * @param row Row number 120 * @param channel Channel number 121 * @param cell Place to store decoded cell 122 */ 123 static void protracker_decode_cell(uint32_t cdata, trackmod_cell_t *cell) 124 { 125 uint32_t code; 126 127 code = uint32_t_be2host(cdata); 128 cell->period = (code >> (4 * 4)) & 0xfff; 129 cell->instr = (((code >> (7 * 4)) & 0xf) << 4) | 130 ((code >> (3 * 4)) & 0xf); 131 cell->effect = code & 0xfff; 132 } 133 134 /** Load Protracker patterns. 135 * 136 * @param f File to read from 137 * @param module Module being loaded to 138 * @return EOK on success, ENOMEM if out of memory, EIO on I/O error. 139 */ 140 static int protracker_load_patterns(FILE *f, trackmod_module_t *module) 141 { 142 size_t cells; 143 size_t i, j; 144 int rc; 145 size_t nread; 146 uint32_t *buf = NULL; 147 148 cells = module->channels * protracker_pattern_rows; 149 buf = calloc(sizeof(uint32_t), cells); 150 151 if (buf == NULL) { 152 rc = ENOMEM; 153 goto error; 154 } 155 156 for (i = 0; i < module->patterns; i++) { 157 module->pattern[i].rows = protracker_pattern_rows; 158 module->pattern[i].channels = module->channels; 159 module->pattern[i].data = calloc(sizeof(trackmod_cell_t), cells); 160 if (module->pattern[i].data == NULL) { 161 rc = ENOMEM; 162 goto error; 163 } 164 165 nread = fread(buf, sizeof(uint32_t), cells, f); 166 if (nread != cells) { 167 printf("Error reading pattern.\n"); 168 rc = EIO; 169 goto error; 170 } 171 172 /* Decode cells */ 173 for (j = 0; j < cells; j++) { 174 protracker_decode_cell(buf[j], 175 &module->pattern[i].data[j]); 176 } 177 } 178 179 free(buf); 180 return EOK; 181 error: 182 free(buf); 183 return rc; 184 } 185 186 /** Load protracker samples. 187 * 188 * @param f File being read from 189 * @param sample Sample header 190 * @param module Module being loaded to 191 * @return EOk on success, ENOMEM if out of memory, EIO on I/O error. 192 */ 193 static int protracker_load_samples(FILE *f, protracker_smp_t *smp, 194 trackmod_module_t *module) 195 { 196 int rc; 197 size_t i; 198 uint8_t ftval; 199 size_t nread; 200 trackmod_sample_t *sample; 201 202 for (i = 0; i < module->instrs; i++) { 203 module->instr[i].samples = 1; 204 module->instr[i].sample = calloc(1, sizeof(trackmod_sample_t)); 205 if (module->instr[i].sample == NULL) { 206 printf("Error allocating sample.\n"); 207 rc = ENOMEM; 208 goto error; 209 } 210 211 sample = &module->instr[i].sample[0]; 212 sample->length = 213 uint16_t_be2host(smp[i].length) * 2; 214 sample->bytes_smp = 1; 215 sample->data = calloc(1, sample->length); 216 if (sample->data == NULL) { 217 printf("Error allocating sample.\n"); 218 rc = ENOMEM; 219 goto error; 220 } 221 222 nread = fread(sample->data, 1, sample->length, f); 223 if (nread != sample->length) { 224 printf("Error reading sample.\n"); 225 rc = EIO; 226 goto error; 227 } 228 229 sample->def_vol = smp[i].def_vol; 230 231 sample->loop_start = 232 uint16_t_be2host(smp[i].loop_start) * 2; 233 sample->loop_len = 234 uint16_t_be2host(smp[i].loop_len) * 2; 235 if (sample->loop_len <= 2) 236 sample->loop_type = tl_no_loop; 237 else 238 sample->loop_type = tl_forward_loop; 239 240 /* Finetune is a 4-bit signed value. */ 241 ftval = smp[i].finetune & 0x0f; 242 sample->finetune = 243 (ftval & 0x8) ? (ftval & 0x7) - 8 : ftval; 244 } 245 246 return EOK; 247 error: 248 return rc; 249 } 250 115 251 /** Load protracker module. 116 252 * … … 128 264 protracker_order_list_t *order_list; 129 265 protracker_smp_t *sample; 130 size_t nread;131 266 size_t samples; 132 267 size_t channels; 133 268 size_t patterns; 134 size_t cells;135 size_t i, j;269 size_t i; 270 size_t nread; 136 271 int rc; 137 272 … … 192 327 module->channels = channels; 193 328 194 module-> samples = samples;195 module-> sample = calloc(sizeof(trackmod_sample_t), samples);196 if (module-> sample== NULL) {329 module->instrs = samples; 330 module->instr = calloc(sizeof(trackmod_instr_t), samples); 331 if (module->instr == NULL) { 197 332 printf("Out of memory.\n"); 198 333 rc = ENOMEM; … … 221 356 } 222 357 358 /* The 'mark' byte may or may not contain a valid restart position */ 359 if (order_list->mark < order_list->order_list_len) { 360 module->restart_pos = order_list->mark; 361 } 362 223 363 /* Load patterns */ 224 225 cells = channels * protracker_pattern_rows; 226 227 for (i = 0; i < patterns; i++) { 228 module->pattern[i].rows = protracker_pattern_rows; 229 module->pattern[i].channels = channels; 230 module->pattern[i].data = calloc(sizeof(uint32_t), cells); 231 232 nread = fread(module->pattern[i].data, 233 sizeof(uint32_t), cells, f); 234 if (nread != cells) { 235 printf("Error reading pattern.\n"); 236 rc = EIO; 237 goto error; 238 } 239 240 /* Convert byte order */ 241 for (j = 0; j < cells; j++) { 242 module->pattern[i].data[j] = uint32_t_be2host( 243 module->pattern[i].data[j]); 244 } 245 } 364 rc = protracker_load_patterns(f, module); 365 if (rc != EOK) 366 goto error; 246 367 247 368 /* Load samples */ 248 for (i = 0; i < samples; i++) { 249 module->sample[i].length = 250 uint16_t_be2host(sample[i].length) * 2; 251 module->sample[i].data = calloc(1, module->sample[i].length); 252 if (module->sample[i].data == NULL) { 253 printf("Error allocating sample.\n"); 254 rc = ENOMEM; 255 goto error; 256 } 257 258 nread = fread(module->sample[i].data, 1, module->sample[i].length, 259 f); 260 if (nread != module->sample[i].length) { 261 printf("Error reading sample.\n"); 262 rc = EIO; 263 goto error; 264 } 265 266 module->sample[i].def_vol = sample[i].def_vol; 267 module->sample[i].loop_start = 268 uint16_t_be2host(sample[i].loop_start) * 2; 269 module->sample[i].loop_len = 270 uint16_t_be2host(sample[i].loop_len) * 2; 271 if (module->sample[i].loop_len <= 2) 272 module->sample[i].loop_len = 0; 273 } 369 rc = protracker_load_samples(f, sample, module); 370 if (rc != EOK) 371 goto error; 274 372 275 373 (void) fclose(f); 374 375 module->def_bpm = protracker_def_bpm; 376 module->def_tpr = protracker_def_tpr; 276 377 277 378 *rmodule = module; -
uspace/lib/trackmod/trackmod.c
ref3da5a rb412168 40 40 41 41 #include "macros.h" 42 #include "protracker.h" 42 43 #include "trackmod.h" 44 #include "xm.h" 43 45 44 46 /** Tunables */ … … 52 54 base_clock = 8363 * 428, 53 55 /** Maximum sample volume */ 54 vol_max = 6 3,55 /** Default TPR*/56 def_tpr = 6,57 /** Default BPM*/58 def_bpm = 12556 vol_max = 64, 57 /** Minimum period */ 58 period_min = 113, 59 /** Maxium period */ 60 period_max = 856 59 61 }; 60 62 63 /** Table for finetune computation. 64 * 65 * Finetune is a number ft in [-8 .. 7]. The pitch should be adjusted by 66 * ft/8 semitones. To adjust pitch by 1/8 semitone down we can mutiply the 67 * period by 2^(1/12/8) =. 1.0072, one semitone up: 2^-(1/12/8) =. 0.9928, 68 * to adjust by ft/8 semitones, multiply by 2^(-ft/12/8). 69 * 70 * finetune_factor[ft] := 10000 * 2^(-ft/12/8) 71 * res_period = clip(period * fineture_factor[ft+8] / 10000) 72 */ 73 static unsigned finetune_factor[16] = { 74 10595, 10518, 10443, 10368, 10293, 10219, 10145, 10072, 75 10000, 9928, 9857, 9786, 9715, 9645, 9576, 9507 76 }; 77 78 static unsigned period_table[12 * 8] = { 79 907,900,894,887,881,875,868,862,856,850,844,838,832,826,820,814, 80 808,802,796,791,785,779,774,768,762,757,752,746,741,736,730,725, 81 720,715,709,704,699,694,689,684,678,675,670,665,660,655,651,646, 82 640,636,632,628,623,619,614,610,604,601,597,592,588,584,580,575, 83 570,567,563,559,555,551,547,543,538,535,532,528,524,520,516,513, 84 508,505,502,498,494,491,487,484,480,477,474,470,467,463,460,457 85 }; 86 61 87 static size_t trackmod_get_next_ord_idx(trackmod_modplay_t *); 62 88 … … 70 96 } 71 97 98 /** Destroy instrument. 99 * 100 * @param instr Intrument 101 */ 102 static void trackmod_instr_destroy(trackmod_instr_t *instr) 103 { 104 size_t i; 105 106 for (i = 0; i < instr->samples; i++) 107 trackmod_sample_destroy(&instr->sample[i]); 108 } 109 72 110 /** Destroy pattern. 73 111 * … … 97 135 98 136 /* Destroy samples */ 99 if (module-> sample!= NULL) {100 for (i = 0; i < module-> samples; i++)101 trackmod_ sample_destroy(&module->sample[i]);102 free(module-> sample);137 if (module->instr != NULL) { 138 for (i = 0; i < module->instrs; i++) 139 trackmod_instr_destroy(&module->instr[i]); 140 free(module->instr); 103 141 } 104 142 … … 114 152 } 115 153 154 int trackmod_module_load(char *fname, trackmod_module_t **rmodule) 155 { 156 int rc; 157 158 rc = trackmod_xm_load(fname, rmodule); 159 if (rc == EOK) 160 return EOK; 161 162 rc = trackmod_protracker_load(fname, rmodule); 163 return rc; 164 } 165 166 116 167 /** Return current pattern. 117 168 * … … 137 188 size_t row, size_t channel, trackmod_cell_t *cell) 138 189 { 139 uint32_t code; 140 141 code = pattern->data[row * pattern->channels + channel]; 142 cell->period = (code >> (4 * 4)) & 0xfff; 143 cell->sample = (((code >> (7 * 4)) & 0xf) << 4) | 144 ((code >> (3 * 4)) & 0xf); 145 cell->effect = code & 0xfff; 146 } 147 148 /** Process note (period, sample index) 190 *cell = pattern->data[row * pattern->channels + channel]; 191 } 192 193 /** Compute floor(a / b), and the remainder. 194 * 195 * Unlike standard integer division this rounds towars negative infinity, 196 * not towards zero. 197 * 198 * @param a Dividend 199 * @param b Divisor 200 * @param quot Place to store 'quotient' (floor (a/b)) 201 * @param rem Place to store 'remainder' (a - floor(a/b) * b) 202 */ 203 static void divmod_floor(int a, int b, int *quot, int *rem) 204 { 205 if (b < 0) { 206 a = -a; 207 b = -b; 208 } 209 210 if (a >= 0) { 211 *quot = a / b; 212 *rem = a % b; 213 } else { 214 *quot = - (-a + (b - 1)) / b; 215 *rem = a - (*quot * b); 216 } 217 } 218 219 /** Process note (period) 149 220 * 150 221 * @param modplay Module playback … … 156 227 { 157 228 trackmod_chan_t *chan = &modplay->chan[i]; 158 size_t smpidx; 159 160 smpidx = (cell->sample - 1) % modplay->module->samples; 161 chan->sample = &modplay->module->sample[smpidx]; 229 int period; 230 int pitch; 231 int octave; 232 int opitch; 233 234 if (chan->sample == NULL) 235 return; 236 237 if (cell->period == 0) { 238 pitch = 8 * (cell->note + chan->sample->rel_note) + 239 chan->sample->finetune; 240 divmod_floor(pitch, 8 * 12, &octave, &opitch); 241 242 if (octave >= 0) 243 period = period_table[opitch] * 8 / (1 << octave); 244 else 245 period = period_table[opitch] * 8 * (1 << (-octave)); 246 } else { 247 period = cell->period; 248 period = period * 249 finetune_factor[chan->sample->finetune + 8] / 10000; 250 if (period > period_max) 251 period = period_max; 252 if (period < period_min) 253 period = period_min; 254 } 255 256 chan->period_new = period; 257 } 258 259 /** Process instrument number (this is what triggers the note playback) 260 * 261 * @param modplay Module playback 262 * @param i Channel number 263 * @param cell Cell 264 */ 265 static void trackmod_process_instr(trackmod_modplay_t *modplay, size_t i, 266 trackmod_cell_t *cell) 267 { 268 trackmod_chan_t *chan = &modplay->chan[i]; 269 trackmod_instr_t *instr; 270 size_t iidx; 271 size_t sidx; 272 273 if (cell->instr == 0) 274 return; 275 276 iidx = (cell->instr - 1) % modplay->module->instrs; 277 instr = &modplay->module->instr[iidx]; 278 sidx = instr->key_smp[cell->note] % instr->samples; 279 chan->sample = &instr->sample[sidx]; 162 280 chan->smp_pos = 0; 163 281 chan->lsmp = 0; 164 chan->period = cell->period; 282 165 283 chan->volume = modplay->chan[i].sample->def_vol; 284 } 285 286 /** Process keyoff note 287 * 288 * @param modplay Module playback 289 * @param i Channel number 290 * @param cell Cell 291 */ 292 static void trackmod_process_keyoff_note(trackmod_modplay_t *modplay, size_t i) 293 { 294 trackmod_chan_t *chan = &modplay->chan[i]; 295 296 chan->sample = NULL; 297 chan->period = 0; 298 chan->smp_pos = 0; 299 chan->lsmp = 0; 166 300 } 167 301 … … 175 309 uint8_t param) 176 310 { 177 modplay->chan[chan].volume = param & vol_max;311 modplay->chan[chan].volume = param % (vol_max + 1); 178 312 } 179 313 … … 189 323 size_t next_idx; 190 324 trackmod_pattern_t *next_pat; 325 unsigned row; 326 327 /* Strangely the parameter is BCD */ 328 row = (param >> 4) * 10 + (param & 0xf); 191 329 192 330 next_idx = trackmod_get_next_ord_idx(modplay); … … 194 332 195 333 modplay->pat_break = true; 196 modplay->pat_break_row = param% next_pat->rows;334 modplay->pat_break_row = row % next_pat->rows; 197 335 } 198 336 … … 212 350 } 213 351 352 /** Process Fine volume slide down effect. 353 * 354 * @param modplay Module playback 355 * @param chan Channel number 356 * @param param Effect parameter 357 */ 358 static void trackmod_effect_fine_vol_slide_down(trackmod_modplay_t *modplay, 359 size_t chan, uint8_t param) 360 { 361 int nv; 362 363 nv = modplay->chan[chan].volume - param; 364 if (nv < 0) 365 nv = 0; 366 modplay->chan[chan].volume = nv; 367 } 368 369 /** Process Fine volume slide up effect. 370 * 371 * @param modplay Module playback 372 * @param chan Channel number 373 * @param param Effect parameter 374 */ 375 static void trackmod_effect_fine_vol_slide_up(trackmod_modplay_t *modplay, 376 size_t chan, uint8_t param) 377 { 378 int nv; 379 380 nv = modplay->chan[chan].volume + param; 381 if (nv > vol_max) 382 nv = vol_max; 383 modplay->chan[chan].volume = nv; 384 } 385 386 /** Process Volume slide effect. 387 * 388 * @param modplay Module playback 389 * @param chan Channel number 390 * @param param Effect parameter 391 */ 392 static void trackmod_effect_vol_slide(trackmod_modplay_t *modplay, 393 size_t chan, uint8_t param) 394 { 395 if ((param & 0xf0) != 0) 396 modplay->chan[chan].vol_slide = param >> 4; 397 else 398 modplay->chan[chan].vol_slide = -(int)(param & 0xf); 399 } 400 401 /** Process Volume slide down effect. 402 * 403 * @param modplay Module playback 404 * @param chan Channel number 405 * @param param Effect parameter 406 */ 407 static void trackmod_effect_vol_slide_down(trackmod_modplay_t *modplay, 408 size_t chan, uint8_t param4) 409 { 410 modplay->chan[chan].vol_slide = -(int)param4; 411 } 412 413 /** Process Volume slide up effect. 414 * 415 * @param modplay Module playback 416 * @param chan Channel number 417 * @param param Effect parameter 418 */ 419 static void trackmod_effect_vol_slide_up(trackmod_modplay_t *modplay, 420 size_t chan, uint8_t param4) 421 { 422 modplay->chan[chan].vol_slide = param4; 423 } 424 425 /** Process Fine portamento down effect. 426 * 427 * @param modplay Module playback 428 * @param chan Channel number 429 * @param param Effect parameter 430 */ 431 static void trackmod_effect_fine_porta_down(trackmod_modplay_t *modplay, 432 size_t chan, uint8_t param) 433 { 434 int np; 435 436 np = modplay->chan[chan].period + param; 437 if (np > period_max) 438 np = period_max; 439 modplay->chan[chan].period = np; 440 } 441 442 /** Process Fine portamento up effect. 443 * 444 * @param modplay Module playback 445 * @param chan Channel number 446 * @param param Effect parameter 447 */ 448 static void trackmod_effect_fine_porta_up(trackmod_modplay_t *modplay, 449 size_t chan, uint8_t param) 450 { 451 int np; 452 453 np = modplay->chan[chan].period - param; 454 if (np < period_min) 455 np = period_min; 456 modplay->chan[chan].period = np; 457 } 458 459 /** Process Portamento down effect. 460 * 461 * @param modplay Module playback 462 * @param chan Channel number 463 * @param param Effect parameter 464 */ 465 static void trackmod_effect_porta_down(trackmod_modplay_t *modplay, 466 size_t chan, uint8_t param) 467 { 468 modplay->chan[chan].portamento = -(int)param; 469 } 470 471 /** Process Portamento up effect. 472 * 473 * @param modplay Module playback 474 * @param chan Channel number 475 * @param param Effect parameter 476 */ 477 static void trackmod_effect_porta_up(trackmod_modplay_t *modplay, 478 size_t chan, uint8_t param) 479 { 480 modplay->chan[chan].portamento = param; 481 } 482 483 /** Process Tone portamento effect. 484 * 485 * @param modplay Module playback 486 * @param chan Channel number 487 * @param param Effect parameter 488 */ 489 static void trackmod_effect_tone_porta(trackmod_modplay_t *modplay, 490 size_t chan, uint8_t param) 491 { 492 /* Set up tone portamento effect */ 493 modplay->chan[chan].portamento = param; 494 if (modplay->chan[chan].period_new != 0) 495 modplay->chan[chan].period_tgt = modplay->chan[chan].period_new; 496 497 /* Prevent going directly to new period */ 498 modplay->chan[chan].period_new = 0; 499 } 500 501 /** Process volume column. 502 * 503 * @param modplay Module playback 504 * @param chan Channel number 505 * @param cell Cell 506 */ 507 static void trackmod_process_volume(trackmod_modplay_t *modplay, size_t chan, 508 trackmod_cell_t *cell) 509 { 510 uint8_t param4; 511 512 if (cell->volume >= 0x10 && cell->volume <= 0x10 + vol_max) 513 trackmod_effect_set_volume(modplay, chan, cell->volume - 0x10); 514 515 param4 = cell->volume & 0xf; 516 517 switch (cell->volume & 0xf0) { 518 case 0x60: 519 trackmod_effect_vol_slide_down(modplay, chan, param4); 520 break; 521 case 0x70: 522 trackmod_effect_vol_slide_up(modplay, chan, param4); 523 break; 524 case 0x80: 525 trackmod_effect_fine_vol_slide_down(modplay, chan, param4); 526 break; 527 case 0x90: 528 trackmod_effect_fine_vol_slide_up(modplay, chan, param4); 529 break; 530 case 0xf0: 531 trackmod_effect_tone_porta(modplay, chan, param4 << 4); 532 break; 533 default: 534 break; 535 } 536 } 537 214 538 /** Process effect. 215 539 * … … 222 546 { 223 547 uint8_t param8; 548 uint8_t param4; 224 549 225 550 param8 = cell->effect & 0xff; 226 551 227 552 switch (cell->effect & 0xf00) { 553 case 0x100: 554 trackmod_effect_porta_up(modplay, chan, param8); 555 break; 556 case 0x200: 557 trackmod_effect_porta_down(modplay, chan, param8); 558 break; 559 case 0x300: 560 trackmod_effect_tone_porta(modplay, chan, param8); 561 break; 562 case 0xa00: 563 trackmod_effect_vol_slide(modplay, chan, param8); 564 break; 228 565 case 0xc00: 229 566 trackmod_effect_set_volume(modplay, chan, param8); … … 238 575 break; 239 576 } 577 578 param4 = cell->effect & 0xf; 579 580 switch (cell->effect & 0xff0) { 581 case 0xe10: 582 trackmod_effect_fine_porta_up(modplay, chan, param4); 583 break; 584 case 0xe20: 585 trackmod_effect_fine_porta_down(modplay, chan, param4); 586 break; 587 case 0xea0: 588 trackmod_effect_fine_vol_slide_up(modplay, chan, param4); 589 break; 590 case 0xeb0: 591 trackmod_effect_fine_vol_slide_down(modplay, chan, param4); 592 break; 593 } 240 594 } 241 595 … … 249 603 trackmod_cell_t *cell) 250 604 { 251 if (cell->period != 0 && cell->sample != 0) 605 modplay->chan[chan].period_new = 0; 606 607 trackmod_process_instr(modplay, chan, cell); 608 609 if (cell->period != 0 || (cell->note != 0 && cell->note != keyoff_note)) { 252 610 trackmod_process_note(modplay, chan, cell); 253 611 } else if (cell->note == keyoff_note && cell->instr == 0) { 612 trackmod_process_keyoff_note(modplay, chan); 613 } 614 615 trackmod_process_volume(modplay, chan, cell); 254 616 trackmod_process_effect(modplay, chan, cell); 617 618 if (modplay->chan[chan].period_new != 0) 619 modplay->chan[chan].period = modplay->chan[chan].period_new; 255 620 } 256 621 … … 267 632 pattern = trackmod_cur_pattern(modplay); 268 633 634 if (modplay->debug) 635 printf("%02zx: ", modplay->row); 636 269 637 for (i = 0; i < modplay->module->channels; i++) { 270 638 trackmod_pattern_get_cell(pattern, modplay->row, i, &cell); 271 if (modplay->debug) 272 printf("%4d %02x %03x |", cell.period, cell.sample, cell.effect); 639 640 if (modplay->debug) { 641 printf("%4d %02x %02x %03x |", cell.period ? 642 cell.period : cell.note, cell.instr, 643 cell.volume, cell.effect); 644 } 645 273 646 trackmod_process_cell(modplay, i, &cell); 274 647 } … … 289 662 ord_idx = modplay->ord_idx + 1; 290 663 if (ord_idx >= modplay->module->ord_list_len) 291 ord_idx = 0; /* XXX */664 ord_idx = modplay->module->restart_pos; 292 665 293 666 return ord_idx; … … 313 686 } 314 687 688 /** Clear effects at end of row. */ 689 static void trackmod_clear_effects(trackmod_modplay_t *modplay) 690 { 691 size_t i; 692 693 for (i = 0; i < modplay->module->channels; i++) { 694 modplay->chan[i].vol_slide = 0; 695 modplay->chan[i].portamento = 0; 696 } 697 } 698 699 /** Process effects at beginning of tick. */ 700 static void trackmod_process_tick(trackmod_modplay_t *modplay) 701 { 702 trackmod_chan_t *chan; 703 size_t i; 704 int nv; 705 int np; 706 707 for (i = 0; i < modplay->module->channels; i++) { 708 chan = &modplay->chan[i]; 709 710 /* Volume slides */ 711 nv = (int)chan->volume + chan->vol_slide; 712 if (nv < 0) 713 nv = 0; 714 if (nv > vol_max) 715 nv = vol_max; 716 717 chan->volume = nv; 718 719 /* Portamentos */ 720 if (chan->period_tgt == 0) { 721 /* Up or down portamento */ 722 np = (int)chan->period - chan->portamento; 723 } else { 724 /* Tone portamento */ 725 if (chan->period_tgt < chan->period) 726 np = max((int)chan->period_tgt, (int)chan->period - chan->portamento); 727 else 728 np = min((int)chan->period_tgt, (int)chan->period + chan->portamento); 729 } 730 731 /* if (np < period_min) 732 np = period_min; 733 if (np > period_max) 734 np = period_max; 735 */ 736 modplay->chan[i].period = np; 737 } 738 } 739 315 740 /** Advance to next row. 316 741 * … … 320 745 { 321 746 trackmod_pattern_t *pattern; 747 748 /* Clear effect state at end of row */ 749 trackmod_clear_effects(modplay); 322 750 323 751 pattern = trackmod_cur_pattern(modplay); … … 328 756 trackmod_next_pattern(modplay); 329 757 758 trackmod_process_tick(modplay); 330 759 trackmod_process_row(modplay); 331 760 } … … 341 770 if (modplay->tick >= modplay->tpr) 342 771 trackmod_next_row(modplay); 772 else 773 trackmod_process_tick(modplay); 343 774 } 344 775 … … 366 797 modplay->smp = 0; 367 798 368 modplay->tpr = def_tpr;369 modplay->bpm = def_bpm;799 modplay->tpr = module->def_tpr; 800 modplay->bpm = module->def_bpm; 370 801 371 802 modplay->chan = calloc(module->channels, … … 374 805 goto error; 375 806 807 trackmod_process_tick(modplay); 376 808 trackmod_process_row(modplay); 377 809 … … 416 848 } 417 849 850 /** Get sample frame. 851 * 852 * Get frame at the specified sample position. 853 * 854 * @param sample Sample 855 * @param pos Position (frame index) 856 * @return Frame value 857 */ 858 int trackmod_sample_get_frame(trackmod_sample_t *sample, size_t pos) 859 { 860 int8_t *i8p; 861 int16_t *i16p; 862 863 if (sample->bytes_smp == 1) { 864 i8p = (int8_t *)sample->data; 865 return i8p[pos]; 866 } else { 867 /* chan->sample->bytes_smp == 2 */ 868 i16p = (int16_t *)sample->data; 869 return i16p[pos] / 256; /* XXX Retain full precision */ 870 } 871 } 872 418 873 /** Advance sample position to next frame. 419 874 * … … 422 877 static void chan_smp_next_frame(trackmod_chan_t *chan) 423 878 { 424 chan->lsmp = chan->sample->data[chan->smp_pos];879 chan->lsmp = trackmod_sample_get_frame(chan->sample, chan->smp_pos); 425 880 ++chan->smp_pos; 426 881 427 if (chan->sample->loop_len == 0) { 428 /* No looping */ 882 switch (chan->sample->loop_type) { 883 case tl_pingpong_loop: 884 /** XXX Pingpong loop */ 885 case tl_no_loop: 886 /* No loop */ 429 887 if (chan->smp_pos >= chan->sample->length) { 430 888 chan->sample = NULL; 431 889 chan->smp_pos = 0; 432 890 } 433 } else { 434 /** Looping */ 891 break; 892 case tl_forward_loop: 893 /** Forward loop */ 435 894 if (chan->smp_pos >= chan->sample->loop_start + 436 895 chan->sample->loop_len) { … … 455 914 trackmod_chan_t *chan = &modplay->chan[cidx]; 456 915 457 if (chan->sample == NULL )916 if (chan->sample == NULL || chan->period == 0) 458 917 return 0; 459 918 … … 464 923 */ 465 924 sl = (int)chan->lsmp * amp_factor * chan->volume / vol_max; 466 sn = (int) chan->sample->data[chan->smp_pos] * amp_factor*467 chan->volume / vol_max;925 sn = (int)trackmod_sample_get_frame(chan->sample, chan->smp_pos) * 926 amp_factor * chan->volume / vol_max; 468 927 469 928 period = (int)chan->period; -
uspace/lib/trackmod/trackmod.h
ref3da5a rb412168 40 40 41 41 extern trackmod_module_t *trackmod_module_new(void); 42 extern int trackmod_module_load(char *, trackmod_module_t **); 42 43 extern void trackmod_module_destroy(trackmod_module_t *); 43 44 extern int trackmod_modplay_create(trackmod_module_t *, unsigned, … … 45 46 extern void trackmod_modplay_destroy(trackmod_modplay_t *); 46 47 extern void trackmod_modplay_get_samples(trackmod_modplay_t *, void *, size_t); 48 extern int trackmod_sample_get_frame(trackmod_sample_t *, size_t); 47 49 48 50 #endif -
uspace/lib/trackmod/types/protracker.h
ref3da5a rb412168 47 47 protracker_olist_len = 128, 48 48 /** Number of rows in a pattern */ 49 protracker_pattern_rows = 64 49 protracker_pattern_rows = 64, 50 /** Default TPR */ 51 protracker_def_tpr = 6, 52 /** Default BPM */ 53 protracker_def_bpm = 125 50 54 }; 51 55 -
uspace/lib/trackmod/types/trackmod.h
ref3da5a rb412168 41 41 #include <stdint.h> 42 42 43 enum { 44 max_key = 96, 45 keyoff_note = 97 46 }; 47 48 typedef enum { 49 /** No loop */ 50 tl_no_loop, 51 /** Forward loop */ 52 tl_forward_loop, 53 /** Pingpong loop */ 54 tl_pingpong_loop 55 } trackmod_looptype_t; 56 43 57 /** Sample */ 44 58 typedef struct { 45 59 /** Length in frames */ 46 60 size_t length; 61 /** Bytes per sample */ 62 size_t bytes_smp; 47 63 /** Sample data */ 48 int8_t *data; 64 void *data; 65 /** Loop type */ 66 trackmod_looptype_t loop_type; 49 67 /** Loop start position in frames */ 50 68 size_t loop_start; 51 /** Loop length in frames or 0 - no looping*/69 /** Loop length in frames (> 0) */ 52 70 size_t loop_len; 53 71 /** Default volume (0..63) */ 54 72 uint8_t def_vol; 73 /** Relative note */ 74 int rel_note; 75 /** Finetune value (-8..7) in 1/8 semitones */ 76 int finetune; 55 77 } trackmod_sample_t; 78 79 /** Instrument */ 80 typedef struct { 81 /** Number of samples */ 82 size_t samples; 83 /** Samples */ 84 trackmod_sample_t *sample; 85 /** Sample index for each key */ 86 int key_smp[max_key]; 87 } trackmod_instr_t; 88 89 /** Pattern cell */ 90 typedef struct { 91 /** Note */ 92 unsigned note; 93 /** Sample period */ 94 unsigned period; 95 /** Instrument number */ 96 unsigned instr; 97 /** Volume */ 98 uint8_t volume; 99 /** Effect */ 100 uint16_t effect; 101 } trackmod_cell_t; 56 102 57 103 /** Pattern */ … … 62 108 size_t channels; 63 109 /** Pattern data */ 64 uint32_t *data;110 trackmod_cell_t *data; 65 111 } trackmod_pattern_t; 66 112 … … 70 116 size_t channels; 71 117 /** Number of samples */ 72 size_t samples;73 /** Samples */74 trackmod_ sample_t *sample;118 size_t instrs; 119 /** Instruments */ 120 trackmod_instr_t *instr; 75 121 /** Number of patterns */ 76 122 size_t patterns; … … 81 127 /** Order list */ 82 128 size_t *ord_list; 129 /** Restart pos */ 130 size_t restart_pos; 131 /** Default BPM */ 132 unsigned def_bpm; 133 /** Default TPR */ 134 unsigned def_tpr; 83 135 } trackmod_module_t; 84 136 … … 92 144 /** Sample position (clock ticks within frame) */ 93 145 size_t smp_clk; 94 /** Period */146 /** Current period */ 95 147 unsigned period; 148 /** Period after note was processed, zero if no note */ 149 unsigned period_new; 96 150 /** Volume */ 97 151 uint8_t volume; 152 /** Volume slide amount */ 153 int vol_slide; 154 /** Portamento amount (positive for tone and up portamento, 155 * negative for down portamento. */ 156 int portamento; 157 /** Tone portamento target period. */ 158 unsigned period_tgt; 98 159 } trackmod_chan_t; 99 160 … … 132 193 } trackmod_modplay_t; 133 194 134 /** Pattern cell (decoded) */135 typedef struct {136 /** Sample period */137 unsigned period;138 /** Sample number */139 unsigned sample;140 /** Effect */141 unsigned effect;142 } trackmod_cell_t;143 144 195 #endif 145 196
Note:
See TracChangeset
for help on using the changeset viewer.