Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset b412168 in mainline


Ignore:
Timestamp:
2014-11-17T03:25:04Z (6 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
master
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.
Message:

merge mainline changes

Files:
45 added
34 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    ref3da5a rb412168  
    168168
    169169RD_APPS_NON_ESSENTIAL = \
     170        $(USPACE_PATH)/app/barber/barber \
    170171        $(USPACE_PATH)/app/bithenge/bithenge \
    171172        $(USPACE_PATH)/app/blkdump/blkdump \
  • kernel/generic/src/sysinfo/stats.c

    ref3da5a rb412168  
    8080static mutex_t load_lock;
    8181
    82 /** Get system uptime
    83  *
    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 
    9682/** Get statistics of all CPUs
    9783 *
     
    818804        mutex_initialize(&load_lock, MUTEX_PASSIVE);
    819805       
    820         sysinfo_set_item_gen_val("system.uptime", NULL, get_stats_uptime, NULL);
    821806        sysinfo_set_item_gen_data("system.cpus", NULL, get_stats_cpus, NULL);
    822807        sysinfo_set_item_gen_data("system.physmem", NULL, get_stats_physmem, NULL);
  • uspace/Makefile

    ref3da5a rb412168  
    3434
    3535DIRS = \
     36        app/barber \
    3637        app/bdsh \
    3738        app/bithenge \
     
    211212        lib/fmtutil \
    212213        lib/scsi \
     214        lib/compress \
    213215        lib/softint \
    214216        lib/softfloat \
  • uspace/Makefile.common

    ref3da5a rb412168  
    144144LIBNIC_PREFIX = $(LIB_PREFIX)/nic
    145145LIBMINIX_PREFIX = $(LIB_PREFIX)/minix
     146LIBCOMPRESS_PREFIX = $(LIB_PREFIX)/compress
    146147
    147148LIBSCSI_PREFIX = $(LIB_PREFIX)/scsi
  • uspace/app/bnchmark/bnchmark.c

    ref3da5a rb412168  
    6262{
    6363        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);
    7267        if (rc != EOK) {
    7368                fprintf(stderr, "measured function failed\n");
    7469                return rc;
    7570        }
    76 
     71       
    7772        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);
    8374       
    8475        /* Calculate time difference in milliseconds */
     
    9283        char *path = (char *) data;
    9384        char *buf = malloc(BUFSIZE);
    94 
    95         if (buf == NULL) {
     85       
     86        if (buf == NULL)
    9687                return ENOMEM;
    97         }
    9888       
    9989        FILE *file = fopen(path, "r");
  • uspace/app/init/init.c

    ref3da5a rb412168  
    355355        int rc = compositor(HID_INPUT, HID_COMPOSITOR_SERVER);
    356356        if (rc == EOK) {
     357                gui_start("/app/barber", HID_COMPOSITOR_SERVER);
    357358                gui_start("/app/vlaunch", HID_COMPOSITOR_SERVER);
    358359                gui_start("/app/vterm", HID_COMPOSITOR_SERVER);
  • uspace/app/modplay/modplay.c

    ref3da5a rb412168  
    4040#include <stdio.h>
    4141#include <stdlib.h>
    42 #include <protracker.h>
    4342#include <trackmod.h>
    4443
     
    8887        con = console_init(stdin, stdout);
    8988
    90         rc = trackmod_protracker_load(argv[1], &mod);
     89        rc = trackmod_module_load(argv[1], &mod);
    9190        if (rc != EOK) {
    9291                printf("Error loading %s.\n", argv[1]);
  • uspace/app/nettest1/nettest1.c

    ref3da5a rb412168  
    402402       
    403403        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);
    409405       
    410406        nettest1_test(socket_ids,       1,        1);
     
    414410       
    415411        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);
    421413       
    422414        printf("Tested in %ld microseconds\n", tv_sub(&time_after,
  • uspace/app/nettest2/nettest2.c

    ref3da5a rb412168  
    356356       
    357357        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);
    363359       
    364360        rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address,
     
    368364       
    369365        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);
    375367       
    376368        if (verbose)
     
    380372            tv_sub(&time_after, &time_before));
    381373       
    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);
    387375       
    388376        rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen,
     
    396384                return rc;
    397385       
    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);
    403387       
    404388        if (verbose)
  • uspace/app/stats/stats.c

    ref3da5a rb412168  
    191191static void print_uptime(void)
    192192{
    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);
    198199}
    199200
  • uspace/app/tester/ipc/ping_pong.c

    ref3da5a rb412168  
    4343       
    4444        struct timeval start;
    45         if (gettimeofday(&start, NULL) != 0) {
    46                 TPRINTF("\n");
    47                 return "Failed getting the time";
    48         }
     45        gettimeofday(&start, NULL);
    4946       
    5047        uint64_t count = 0;
    5148        while (true) {
    5249                struct timeval now;
    53                 if (gettimeofday(&now, NULL) != 0) {
    54                         TPRINTF("\n");
    55                         return "Failed getting the time";
    56                 }
     50                gettimeofday(&now, NULL);
    5751               
    5852                if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
  • uspace/app/tester/ipc/starve.c

    ref3da5a rb412168  
    4040        const char *err = NULL;
    4141        console_ctrl_t *console = console_init(stdin, stdout);
    42         if (console == NULL) {
     42        if (console == NULL)
    4343                return "Failed to init connection with console.";
    44         }
    4544       
    4645        struct timeval start;
    47         if (gettimeofday(&start, NULL) != 0) {
    48                 err = "Failed getting the time";
    49                 goto leave;
    50         }
     46        gettimeofday(&start, NULL);
    5147       
    5248        TPRINTF("Intensive computation shall be imagined (for %ds)...\n", DURATION_SECS);
     
    5450        while (true) {
    5551                struct timeval now;
    56                 if (gettimeofday(&now, NULL) != 0) {
    57                         err = "Failed getting the time";
    58                         goto leave;
    59                 }
     52                gettimeofday(&now, NULL);
    6053               
    6154                if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
     
    7063                }
    7164        }
    72 
     65       
    7366        // FIXME - unless a key was pressed, the answer leaked as no one
    7467        // will wait for it.
    7568        // We cannot use async_forget() directly, though. Something like
    7669        // console_forget_pending_kbd_event() shall come here.
    77 
     70       
    7871        TPRINTF("Terminating...\n");
    79 
    80 leave:
     72       
    8173        console_done(console);
    82 
     74       
    8375        return err;
    8476}
  • uspace/app/testread/testread.c

    ref3da5a rb412168  
    123123        struct timeval prev_time;
    124124        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);
    133126        prev_time = start_time;
    134127       
     
    155148                if (progress && offset >= next_mark) {
    156149                        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                       
    164152                        uint32_t last_run = cur_time.tv_sec - prev_time.tv_sec;
    165153                        uint32_t total_time = cur_time.tv_sec - start_time.tv_sec;
     
    178166       
    179167        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);
    187169       
    188170        uint32_t total_run_time = final_time.tv_sec - start_time.tv_sec;
  • uspace/app/top/top.c

    ref3da5a rb412168  
    156156        /* Get current time */
    157157        struct timeval time;
    158         if (gettimeofday(&time, NULL) != EOK)
    159                 return "Cannot get time of day";
     158        gettimeofday(&time, NULL);
    160159       
    161160        target->hours = (time.tv_sec % DAY) / HOUR;
     
    164163       
    165164        /* 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;
    171172       
    172173        /* Get load */
  • uspace/app/vlaunch/vlaunch.c

    ref3da5a rb412168  
    3737#include <stdio.h>
    3838#include <malloc.h>
    39 #include <io/pixel.h>
    4039#include <task.h>
    41 #include <str.h>
    4240#include <str_error.h>
    43 #include <loc.h>
    44 #include <fibril_synch.h>
    45 #include <io/pixel.h>
    46 #include <device/led_dev.h>
    4741
    4842#include <window.h>
     
    6458#define LOGO_HEIGHT  66
    6559
    66 #define PERIOD  1000000
    67 #define COLORS  7
    68 
    6960static 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;
    9061
    9162static int app_launch(const char *app)
     
    129100}
    130101
    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 removal
    185        
    186         free(svcs);
    187 }
    188 
    189102int main(int argc, char *argv[])
    190103{
    191104        if (argc < 2) {
    192105                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");
    206106                return 1;
    207107        }
     
    262162        window_exec(main_window);
    263163       
    264         fibril_timer_set(timer, PERIOD, timer_callback, NULL);
    265        
    266164        task_retval(0);
    267165        async_manager();
  • uspace/dist/src/c/demos/tetris/shapes.c

    ref3da5a rb412168  
    6969
    7070const struct shape shapes[] = {
    71         /*  0 */  {  7,  7, { TL, TC, MR }, 0xff042d},
    72         /*  1 */  {  8,  8, { TC, TR, ML }, 0xff9304},
    73         /*  2 */  {  9, 11, { ML, MR, BC }, 0xbeff04},
    74         /*  3 */  {  3,  3, { TL, TC, ML }, 0x63ff04},
    75         /*  4 */  { 12, 14, { ML, BL, MR }, 0xce04ff},
    76         /*  5 */  { 15, 17, { ML, BR, MR }, 0xff04cf},
    77         /*  6 */  { 18, 18, { ML, MR, 2  }, 0x7604ff},  /* sticks out */
    78         /*  7 */  {  0,  0, { TC, ML, BL }, 0xff042d},
    79         /*  8 */  {  1,  1, { TC, MR, BR }, 0xff9304},
    80         /*  9 */  { 10,  2, { TC, MR, BC }, 0xbeff04},
    81         /* 10 */  { 11,  9, { TC, ML, MR }, 0xbeff04},
    82         /* 11 */  {  2, 10, { TC, ML, BC }, 0xbeff04},
    83         /* 12 */  { 13,  4, { TC, BC, BR }, 0xce04ff},
    84         /* 13 */  { 14, 12, { TR, ML, MR }, 0xce04ff},
    85         /* 14 */  {  4, 13, { TL, TC, BC }, 0xce04ff},
    86         /* 15 */  { 16,  5, { TR, TC, BC }, 0xff04cf},
    87         /* 16 */  { 17, 15, { TL, MR, ML }, 0xff04cf},
    88         /* 17 */  {  5, 16, { TC, BC, BL }, 0xff04cf},
    89         /* 18 */  {  6,  6, { TC, BC, 2 * B_COLS }, 0x7604ff}  /* 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 */
    9090};
    9191
  • uspace/dist/src/c/demos/top/screen.c

    ref3da5a rb412168  
    3737
    3838#include <stdio.h>
     39#include <stdlib.h>
    3940#include <io/console.h>
    4041#include <io/style.h>
     
    4344#include <stats.h>
    4445#include <inttypes.h>
     46#include <macros.h>
    4547#include "screen.h"
    4648#include "top.h"
     
    4850#define USEC_COUNT  1000000
    4951
    50 static sysarg_t warn_col = 0;
    51 static sysarg_t warn_row = 0;
    5252static suseconds_t timeleft = 0;
    5353
    5454console_ctrl_t *console;
    5555
     56static sysarg_t warning_col = 0;
     57static sysarg_t warning_row = 0;
     58static suseconds_t warning_timeleft = 0;
     59static char *warning_text = NULL;
     60
    5661static void screen_style_normal(void)
    5762{
     
    6469        console_flush(console);
    6570        console_set_style(console, STYLE_INVERTED);
     71}
     72
     73static void screen_style_emphasis(void)
     74{
     75        console_flush(console);
     76        console_set_style(console, STYLE_EMPHASIS);
    6677}
    6778
     
    126137void screen_done(void)
    127138{
     139        free(warning_text);
     140        warning_text = NULL;
     141
    128142        screen_restart(true);
    129143       
     
    277291}
    278292
    279 static inline void print_tasks_head(void)
     293static inline void print_help_head(void)
    280294{
    281295        screen_style_inverted();
    282         printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
    283             " [%%user] [%%kern] [name");
     296        printf("Help");
    284297        screen_newline();
    285298        screen_style_normal();
    286299}
    287300
    288 static inline void print_tasks(data_t *data)
    289 {
    290         sysarg_t cols;
    291         sysarg_t rows;
    292         screen_get_size(&cols, &rows);
     301static 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();
    293340       
    294341        sysarg_t col;
     
    296343        screen_get_pos(&col, &row);
    297344       
    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        
    326345        while (row < rows) {
    327346                screen_newline();
     
    330349}
    331350
    332 static inline void print_ipc_head(void)
    333 {
     351static 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
    334357        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        }
    337372        screen_newline();
    338373        screen_style_normal();
    339374}
    340375
    341 static inline void print_ipc(data_t *data)
     376static inline void print_table(const table_t *table)
    342377{
    343378        sysarg_t cols;
     
    350385       
    351386        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                }
    392441        }
    393442       
     
    398447}
    399448
    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)
     449static inline void print_sort(table_t *table)
    409450{
    410451        sysarg_t cols;
     
    415456        sysarg_t row;
    416457        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);
    441462                screen_newline();
    442463                row++;
     
    449470}
    450471
    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         }
     472static 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();
    484484}
    485485
     
    492492        print_cpu_info(data);
    493493        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);
    503500                break;
    504         case OP_IPC:
    505                 print_ipc_head();
    506                 print_ipc(data);
     501        case SCREEN_SORT:
     502                print_sort(&data->table);
    507503                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();
    514506                print_help();
    515507        }
     
    518510}
    519511
    520 void print_warning(const char *fmt, ...)
    521 {
    522         screen_moveto(warn_col, warn_row);
    523        
     512void 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
    524524        va_list args;
    525525        va_start(args, fmt);
    526         vprintf(fmt, args);
     526        vsnprintf(warning_text, warning_text_size, fmt, args);
    527527        va_end(args);
    528528       
    529         screen_newline();
     529        warning_timeleft = 2 * USEC_COUNT;
     530
     531        screen_moveto(warning_col, warning_row);
     532        print_warning();
    530533        console_flush(console);
    531534}
     
    555558                cons_event_t event;
    556559               
     560                warning_timeleft -= timeleft;
    557561                if (!console_get_event_timeout(console, &event, &timeleft)) {
    558562                        timeleft = 0;
    559563                        return -1;
    560564                }
     565                warning_timeleft += timeleft;
    561566               
    562567                if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
  • uspace/dist/src/c/demos/top/screen.h

    ref3da5a rb412168  
    4444extern void screen_done(void);
    4545extern void print_data(data_t *);
    46 extern void print_warning(const char *, ...)
     46extern void show_warning(const char *, ...)
    4747    PRINTF_ATTRIBUTE(1, 2);
    4848
  • uspace/dist/src/c/demos/top/top.c

    ref3da5a rb412168  
    5555#define MINUTE  60
    5656
    57 op_mode_t op_mode = OP_TASKS;
    58 sort_mode_t sort_mode = SORT_TASK_CYCLES;
    59 bool excs_all = false;
     57typedef enum {
     58        OP_TASKS,
     59        OP_IPC,
     60        OP_EXCS,
     61} op_mode_t;
     62
     63static 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
     75enum {
     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
     88static 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
     98enum {
     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
     109static 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
     118enum {
     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
     128screen_mode_t screen_mode = SCREEN_TABLE;
     129static op_mode_t op_mode = OP_TASKS;
     130static size_t sort_column = TASK_COL_PERCENT_USER;
     131static int sort_reverse = -1;
     132static bool excs_all = false;
    60133
    61134static const char *read_data(data_t *target)
     
    67140        target->tasks = NULL;
    68141        target->tasks_perc = NULL;
    69         target->tasks_map = NULL;
    70142        target->threads = NULL;
    71143        target->exceptions = NULL;
     
    76148        target->ecycles_diff = NULL;
    77149        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;
    78155       
    79156        /* Get current time */
    80157        struct timeval time;
    81         if (gettimeofday(&time, NULL) != EOK)
    82                 return "Cannot get time of day";
     158        gettimeofday(&time, NULL);
    83159       
    84160        target->hours = (time.tv_sec % DAY) / HOUR;
     
    87163       
    88164        /* 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;
    94172       
    95173        /* Get load */
     
    117195        if (target->tasks_perc == NULL)
    118196                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";
    124197       
    125198        /* Get threads */
     
    289362static int cmp_data(void *a, void *b, void *arg)
    290363{
    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
    304396        return 0;
    305397}
    306398
    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);
     399static 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
     408static 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
     447static 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
     480static 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
     516static 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;
    316532}
    317533
     
    356572        if (target->ecount_diff != NULL)
    357573                free(target->ecount_diff);
     574
     575        if (target->table.fields != NULL)
     576                free(target->table.fields);
    358577}
    359578
     
    367586        printf("Reading initial data...\n");
    368587       
    369         if ((ret = read_data(&data_prev)) != NULL)
     588        if ((ret = read_data(&data)) != NULL)
    370589                goto out;
    371590       
    372591        /* Compute some rubbish to have initialised values */
    373         compute_percentages(&data_prev, &data_prev);
     592        compute_percentages(&data, &data);
    374593       
    375594        /* And paint screen until death */
    376595        while (true) {
    377596                int c = tgetchar(UPDATE_INTERVAL);
    378                 if (c < 0) {
     597
     598                if (c < 0) { /* timeout */
     599                        data_prev = data;
    379600                        if ((ret = read_data(&data)) != NULL) {
    380                                 free_data(&data);
     601                                free_data(&data_prev);
    381602                                goto out;
    382603                        }
    383604                       
    384605                        compute_percentages(&data_prev, &data);
    385                         sort_data(&data);
    386                         print_data(&data);
    387606                        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
    393629                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");
    397660                                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);
    425673        }
    426674       
    427675out:
    428676        screen_done();
    429         free_data(&data_prev);
     677        free_data(&data);
    430678       
    431679        if (ret != NULL) {
  • uspace/dist/src/c/demos/top/top.h

    ref3da5a rb412168  
    5151
    5252typedef 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;
    5857
    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;
     58extern screen_mode_t screen_mode;
    6659
    6760typedef struct {
     
    8780} perc_exc_t;
    8881
     82typedef enum {
     83        FIELD_EMPTY, FIELD_UINT, FIELD_UINT_SUFFIX_BIN, FIELD_UINT_SUFFIX_DEC,
     84        FIELD_PERCENT, FIELD_STRING
     85} field_type_t;
     86
     87typedef 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
     96typedef struct {
     97        const char *name;
     98        char key;
     99        int width;
     100} column_t;
     101
     102typedef 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
    89110typedef struct {
    90111        time_t hours;
     
    107128        stats_task_t *tasks;
    108129        perc_task_t *tasks_perc;
    109         size_t *tasks_map;
    110130       
    111131        size_t threads_count;
     
    122142        uint64_t *ecycles_diff;
    123143        uint64_t *ecount_diff;
     144
     145        table_t table;
    124146} data_t;
    125147
  • uspace/lib/c/generic/stats.c

    ref3da5a rb412168  
    291291}
    292292
    293 /** Get system uptime
    294  *
    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 
    307293/** Print load fixed-point value
    308294 *
     
    316302void stats_print_load_fragment(load_t upper, unsigned int dec_length)
    317303{
    318         /* Magic value from BSD */
    319         load_t lower = 65536;
    320        
    321304        /* 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;
    325308       
    326309        unsigned int i;
    327310        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;
    330313        }
    331314}
  • uspace/lib/c/generic/time.c

    ref3da5a rb412168  
    5454#include <malloc.h>
    5555
    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)
    5764
    5865/** Pointer to kernel shared variables with time */
     
    6370} *ktime = NULL;
    6471
    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.
     72static async_sess_t *clock_conn = NULL;
     73
     74/** Check whether the year is a leap year.
    7675 *
    7776 * @param year Year since 1900 (e.g. for 1970, the value is 70).
     77 *
    7878 * @return true if year is a leap year, false otherwise
    79  */
    80 static bool _is_leap_year(time_t year)
     79 *
     80 */
     81static bool is_leap_year(time_t year)
    8182{
    8283        year += 1900;
    83 
     84       
    8485        if (year % 400 == 0)
    8586                return true;
     87       
    8688        if (year % 100 == 0)
    8789                return false;
     90       
    8891        if (year % 4 == 0)
    8992                return true;
     93       
    9094        return false;
    9195}
    9296
    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.
    95100 * Note that year is only taken into account if month is February.
    96101 *
    97102 * @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 *
    99105 * @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 */
     108static 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       
    108117        if (mon == 1) {
     118                /* February */
    109119                year += 1900;
    110                 /* february */
    111                 return _is_leap_year(year) ? 29 : 28;
    112         } else {
    113                 return month_days[mon];
    114         }
    115 }
    116 
    117 /**
    118  * For specified year, month and day of month, returns which day of that year
     120                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
    119129 * it is.
    120130 *
    121131 * For example, given date 2011-01-03, the corresponding expression is:
    122  *     _day_of_year(111, 0, 3) == 2
     132 * day_of_year(111, 0, 3) == 2
    123133 *
    124134 * @param year Year (year 1900 = 0, can be negative).
    125  * @param mon Month (January = 0).
     135 * @param mon  Month (January = 0).
    126136 * @param mday Day of month (First day is 1).
     137 *
    127138 * @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 */
     141static 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.
    142157 *
    143158 * @param op1 Dividend.
    144159 * @param op2 Divisor.
     160 *
    145161 * @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 */
     164static time_t floor_div(time_t op1, time_t op2)
     165{
     166        if ((op1 >= 0) || (op1 % op2 == 0))
    150167                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.
    159175 *
    160176 * @param op1 Dividend.
    161177 * @param op2 Divisor.
     178 *
    162179 * @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 */
     182static 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. */
    174194        assert(result >= 0);
    175195        assert(result < op2);
     
    179199}
    180200
    181 /**
    182  * Number of days since the Epoch.
     201/** Number of days since the Epoch.
     202 *
    183203 * Epoch is 1970-01-01, which is also equal to day 0.
    184204 *
    185205 * @param year Year (year 1900 = 0, may be negative).
    186  * @param mon Month (January = 0).
     206 * @param mon  Month (January = 0).
    187207 * @param mday Day of month (first day = 1).
     208 *
    188209 * @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 */
     212static 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 *
    200223 * @param tm Normalized broken-down time.
     224 *
    201225 * @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 */
     228static time_t secs_since_epoch(const struct tm *tm)
     229{
     230        return days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
    206231            SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
    207232            tm->tm_min * SECS_PER_MIN + tm->tm_sec;
    208233}
    209234
    210 /**
    211  * Which day of week the specified date is.
    212  *
     235/** Which day of week the specified date is.
     236 *
    213237 * @param year Year (year 1900 = 0).
    214  * @param mon Month (January = 0).
     238 * @param mon  Month (January = 0).
    215239 * @param mday Day of month (first = 1).
     240 *
    216241 * @return Day of week (Sunday = 0).
    217  */
    218 static int _day_of_week(time_t year, time_t mon, time_t mday)
     242 *
     243 */
     244static time_t day_of_week(time_t year, time_t mon, time_t mday)
    219245{
    220246        /* 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 of
    226  * 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.
    229255 * @param sec_add Seconds to add.
     256 *
    230257 * @return 0 on success, -1 on overflow
    231  */
    232 static int _normalize_time(struct tm *tm, time_t sec_add)
     258 *
     259 */
     260static int normalize_time(struct tm *tm, time_t sec_add)
    233261{
    234262        // TODO: DST correction
    235 
     263       
    236264        /* Set initial values. */
    237265        time_t sec = tm->tm_sec + sec_add;
     
    241269        time_t mon = tm->tm_mon;
    242270        time_t year = tm->tm_year;
    243 
     271       
    244272        /* 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       
    252280        /* 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       
    256284        /* Now the difficult part - days of month. */
    257285       
    258286        /* 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);
    261289       
    262290        /* Then, go in one year steps. */
     
    264292                /* January and February. */
    265293                while (day > 365) {
    266                         day -= _is_leap_year(year) ? 366 : 365;
     294                        day -= is_leap_year(year) ? 366 : 365;
    267295                        year++;
    268296                }
     
    270298                /* Rest of the year. */
    271299                while (day > 365) {
    272                         day -= _is_leap_year(year + 1) ? 366 : 365;
     300                        day -= is_leap_year(year + 1) ? 366 : 365;
    273301                        year++;
    274302                }
     
    276304       
    277305        /* 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);
    280308                mon++;
     309               
    281310                if (mon >= 12) {
    282311                        mon -= 12;
     
    286315       
    287316        /* 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);
    290319       
    291320        /* And put the values back to the struct. */
     
    296325        tm->tm_mon = (int) mon;
    297326       
    298         /* Casts to work around libc brain-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);
    301330                return -1;
    302331        }
     
    306335}
    307336
    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.
    311341 *
    312342 * @param Year since 1900.
     343 *
    313344 * @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 */
     347static 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.
    323355 *
    324356 * @param tm Normalized broken-down time.
     357 *
    325358 * @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 */
     361static int wbyear(const struct tm *tm)
     362{
     363        int day = tm->tm_yday - wbyear_offset(tm->tm_year);
     364       
    330365        if (day < 0) {
    331366                /* Last week of previous year. */
    332367                return tm->tm_year - 1;
    333368        }
    334         if (day > 364 + _is_leap_year(tm->tm_year)) {
     369       
     370        if (day > 364 + is_leap_year(tm->tm_year)) {
    335371                /* First week of next year. */
    336372                return tm->tm_year + 1;
    337373        }
     374       
    338375        /* All the other days are in the calendar year. */
    339376        return tm->tm_year;
    340377}
    341378
    342 /**
    343  * Week number of the year, assuming weeks start on sunday.
     379/** Week number of the year (assuming weeks start on Sunday).
     380 *
    344381 * The first Sunday of January is the first day of week 1;
    345382 * days in the new year before this are in week 0.
    346383 *
    347384 * @param tm Normalized broken-down time.
     385 *
    348386 * @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 */
     389static int sun_week_number(const struct tm *tm)
     390{
     391        int first_day = (7 - day_of_week(tm->tm_year, 0, 1)) % 7;
     392       
    353393        return (tm->tm_yday - first_day + 7) / 7;
    354394}
    355395
    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
    361402 * of January are always in week 1.
    362403 *
    363404 * @param tm Normalized broken-down time.
     405 *
    364406 * @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 */
     409static int iso_week_number(const struct tm *tm)
     410{
     411        int day = tm->tm_yday - wbyear_offset(tm->tm_year);
     412       
    369413        if (day < 0) {
    370414                /* Last week of previous year. */
    371415                return 53;
    372416        }
    373         if (day > 364 + _is_leap_year(tm->tm_year)) {
     417       
     418        if (day > 364 + is_leap_year(tm->tm_year)) {
    374419                /* First week of next year. */
    375420                return 1;
    376421        }
     422       
    377423        /* All the other days give correct answer. */
    378424        return (day / 7 + 1);
    379425}
    380426
    381 /**
    382  * Week number of the year, assuming weeks start on monday.
     427/** Week number of the year (assuming weeks start on Monday).
     428 *
    383429 * 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.
    385431 *
    386432 * @param tm Normalized broken-down time.
     433 *
    387434 * @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 */
     437static int mon_week_number(const struct tm *tm)
     438{
     439        int first_day = (1 - day_of_week(tm->tm_year, 0, 1)) % 7;
     440       
    392441        return (tm->tm_yday - first_day + 7) / 7;
    393442}
    394 
    395 /******************************************************************************/
    396 
    397443
    398444/** Add microseconds to given timeval.
     
    468514}
    469515
    470 /** Get time of day
     516/** Get time of day.
    471517 *
    472518 * The time variables are memory mapped (read-only) from kernel which
     
    482528 *
    483529 */
    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 
     530void gettimeofday(struct timeval *tv, struct timezone *tz)
     531{
    496532        if (tz) {
    497533                tz->tz_minuteswest = 0;
    498534                tz->tz_dsttime = DST_NONE;
    499535        }
    500 
     536       
    501537        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);
    503540                if (rc != EOK)
    504                         goto ret_uptime;
    505 
     541                        goto fallback;
     542               
     543                service_id_t *svc_ids;
     544                size_t svc_cnt;
    506545                rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
    507546                if (rc != EOK)
    508                         goto ret_uptime;
    509 
     547                        goto fallback;
     548               
    510549                if (svc_cnt == 0)
    511                         goto ret_uptime;
    512 
     550                        goto fallback;
     551               
     552                char *svc_name;
    513553                rc = loc_service_get_name(svc_ids[0], &svc_name);
     554                free(svc_ids);
    514555                if (rc != EOK)
    515                         goto ret_uptime;
    516 
     556                        goto fallback;
     557               
     558                service_id_t svc_id;
    517559                rc = loc_service_get_id(svc_name, &svc_id, 0);
     560                free(svc_name);
    518561                if (rc != EOK)
    519                         goto ret_uptime;
    520 
     562                        goto fallback;
     563               
    521564                clock_conn = loc_service_connect(EXCHANGE_SERIALIZE,
    522565                    svc_id, IPC_FLAG_BLOCKING);
    523566                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);
    528572        if (rc != EOK)
    529                 goto ret_uptime;
    530 
     573                goto fallback;
     574       
    531575        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       
     580fallback:
     581        getuptime(tv);
     582}
     583
     584void getuptime(struct timeval *tv)
    548585{
    549586        if (ktime == NULL) {
     
    552589                if (rc != EOK) {
    553590                        errno = rc;
    554                         return -1;
     591                        goto fallback;
    555592                }
    556593               
     
    561598                        as_area_destroy(addr);
    562599                        errno = rc;
    563                         return -1;
     600                        goto fallback;
    564601                }
    565602               
     
    580617        } else
    581618                tv->tv_sec = s1;
    582 
    583         return 0;
     619       
     620        return;
     621       
     622fallback:
     623        tv->tv_sec = 0;
     624        tv->tv_usec = 0;
    584625}
    585626
     
    587628{
    588629        struct timeval tv;
    589         if (gettimeofday(&tv, NULL))
    590                 return (time_t) -1;
     630        gettimeofday(&tv, NULL);
    591631       
    592632        if (tloc)
     
    631671}
    632672
    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.
    637679 *
    638680 * @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 *
    640685 */
    641686time_t mktime(struct tm *tm)
     
    643688        // TODO: take DST flag into account
    644689        // 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.
    655726 * @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 *
    658730 * @return Number of bytes written.
     731 *
    659732 */
    660733size_t strftime(char *restrict s, size_t maxsize,
     
    664737        assert(format != NULL);
    665738        assert(tm != NULL);
    666 
     739       
    667740        // TODO: use locale
     741       
    668742        static const char *wday_abbr[] = {
    669743                "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    670744        };
     745       
    671746        static const char *wday[] = {
    672747                "Sunday", "Monday", "Tuesday", "Wednesday",
    673748                "Thursday", "Friday", "Saturday"
    674749        };
     750       
    675751        static const char *mon_abbr[] = {
    676752                "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    677753                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    678754        };
     755       
    679756        static const char *mon[] = {
    680757                "January", "February", "March", "April", "May", "June", "July",
     
    682759        };
    683760       
    684         if (maxsize < 1) {
     761        if (maxsize < 1)
    685762                return 0;
    686         }
    687763       
    688764        char *ptr = s;
     
    690766        size_t remaining = maxsize;
    691767       
    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        
    715768        while (*format != '\0') {
    716769                if (*format != '%') {
    717                         append("%c", *format);
     770                        APPEND("%c", *format);
    718771                        format++;
    719772                        continue;
     
    721774               
    722775                format++;
    723                 if (*format == '0' || *format == '+') {
     776                if ((*format == '0') || (*format == '+')) {
    724777                        // TODO: padding
    725778                        format++;
    726779                }
     780               
    727781                while (isdigit(*format)) {
    728782                        // TODO: padding
    729783                        format++;
    730784                }
    731                 if (*format == 'O' || *format == 'E') {
     785               
     786                if ((*format == 'O') || (*format == 'E')) {
    732787                        // TODO: locale's alternative format
    733788                        format++;
     
    736791                switch (*format) {
    737792                case 'a':
    738                         append("%s", wday_abbr[tm->tm_wday]); break;
     793                        APPEND("%s", wday_abbr[tm->tm_wday]);
     794                        break;
    739795                case 'A':
    740                         append("%s", wday[tm->tm_wday]); break;
     796                        APPEND("%s", wday[tm->tm_wday]);
     797                        break;
    741798                case 'b':
    742                         append("%s", mon_abbr[tm->tm_mon]); break;
     799                        APPEND("%s", mon_abbr[tm->tm_mon]);
     800                        break;
    743801                case 'B':
    744                         append("%s", mon[tm->tm_mon]); break;
     802                        APPEND("%s", mon[tm->tm_mon]);
     803                        break;
    745804                case 'c':
    746805                        // TODO: locale-specific datetime format
    747                         recurse("%Y-%m-%d %H:%M:%S"); break;
     806                        RECURSE("%Y-%m-%d %H:%M:%S");
     807                        break;
    748808                case 'C':
    749                         append("%02d", (1900 + tm->tm_year) / 100); break;
     809                        APPEND("%02d", (1900 + tm->tm_year) / 100);
     810                        break;
    750811                case 'd':
    751                         append("%02d", tm->tm_mday); break;
     812                        APPEND("%02d", tm->tm_mday);
     813                        break;
    752814                case 'D':
    753                         recurse("%m/%d/%y"); break;
     815                        RECURSE("%m/%d/%y");
     816                        break;
    754817                case 'e':
    755                         append("%2d", tm->tm_mday); break;
     818                        APPEND("%2d", tm->tm_mday);
     819                        break;
    756820                case 'F':
    757                         recurse("%+4Y-%m-%d"); break;
     821                        RECURSE("%+4Y-%m-%d");
     822                        break;
    758823                case 'g':
    759                         append("%02d", _wbyear(tm) % 100); break;
     824                        APPEND("%02d", wbyear(tm) % 100);
     825                        break;
    760826                case 'G':
    761                         append("%d", _wbyear(tm)); break;
     827                        APPEND("%d", wbyear(tm));
     828                        break;
    762829                case 'h':
    763                         recurse("%b"); break;
     830                        RECURSE("%b");
     831                        break;
    764832                case 'H':
    765                         append("%02d", tm->tm_hour); break;
     833                        APPEND("%02d", tm->tm_hour);
     834                        break;
    766835                case 'I':
    767                         append("%02d", TO_12H(tm->tm_hour)); break;
     836                        APPEND("%02d", TO_12H(tm->tm_hour));
     837                        break;
    768838                case 'j':
    769                         append("%03d", tm->tm_yday); break;
     839                        APPEND("%03d", tm->tm_yday);
     840                        break;
    770841                case 'k':
    771                         append("%2d", tm->tm_hour); break;
     842                        APPEND("%2d", tm->tm_hour);
     843                        break;
    772844                case 'l':
    773                         append("%2d", TO_12H(tm->tm_hour)); break;
     845                        APPEND("%2d", TO_12H(tm->tm_hour));
     846                        break;
    774847                case 'm':
    775                         append("%02d", tm->tm_mon); break;
     848                        APPEND("%02d", tm->tm_mon);
     849                        break;
    776850                case 'M':
    777                         append("%02d", tm->tm_min); break;
     851                        APPEND("%02d", tm->tm_min);
     852                        break;
    778853                case 'n':
    779                         append("\n"); break;
     854                        APPEND("\n");
     855                        break;
    780856                case 'p':
    781                         append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
     857                        APPEND("%s", tm->tm_hour < 12 ? "AM" : "PM");
     858                        break;
    782859                case 'P':
    783                         append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
     860                        APPEND("%s", tm->tm_hour < 12 ? "am" : "PM");
     861                        break;
    784862                case 'r':
    785                         recurse("%I:%M:%S %p"); break;
     863                        RECURSE("%I:%M:%S %p");
     864                        break;
    786865                case 'R':
    787                         recurse("%H:%M"); break;
     866                        RECURSE("%H:%M");
     867                        break;
    788868                case 's':
    789                         append("%ld", _secs_since_epoch(tm)); break;
     869                        APPEND("%ld", secs_since_epoch(tm));
     870                        break;
    790871                case 'S':
    791                         append("%02d", tm->tm_sec); break;
     872                        APPEND("%02d", tm->tm_sec);
     873                        break;
    792874                case 't':
    793                         append("\t"); break;
     875                        APPEND("\t");
     876                        break;
    794877                case 'T':
    795                         recurse("%H:%M:%S"); break;
     878                        RECURSE("%H:%M:%S");
     879                        break;
    796880                case 'u':
    797                         append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
     881                        APPEND("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
    798882                        break;
    799883                case 'U':
    800                         append("%02d", _sun_week_number(tm)); break;
     884                        APPEND("%02d", sun_week_number(tm));
     885                        break;
    801886                case 'V':
    802                         append("%02d", _iso_week_number(tm)); break;
     887                        APPEND("%02d", iso_week_number(tm));
     888                        break;
    803889                case 'w':
    804                         append("%d", tm->tm_wday); break;
     890                        APPEND("%d", tm->tm_wday);
     891                        break;
    805892                case 'W':
    806                         append("%02d", _mon_week_number(tm)); break;
     893                        APPEND("%02d", mon_week_number(tm));
     894                        break;
    807895                case 'x':
    808896                        // TODO: locale-specific date format
    809                         recurse("%Y-%m-%d"); break;
     897                        RECURSE("%Y-%m-%d");
     898                        break;
    810899                case 'X':
    811900                        // TODO: locale-specific time format
    812                         recurse("%H:%M:%S"); break;
     901                        RECURSE("%H:%M:%S");
     902                        break;
    813903                case 'y':
    814                         append("%02d", tm->tm_year % 100); break;
     904                        APPEND("%02d", tm->tm_year % 100);
     905                        break;
    815906                case 'Y':
    816                         append("%d", 1900 + tm->tm_year); break;
     907                        APPEND("%d", 1900 + tm->tm_year);
     908                        break;
    817909                case 'z':
    818910                        // TODO: timezone
     
    822914                        break;
    823915                case '%':
    824                         append("%%");
     916                        APPEND("%%");
    825917                        break;
    826918                default:
    827919                        /* Invalid specifier, print verbatim. */
    828                         while (*format != '%') {
     920                        while (*format != '%')
    829921                                format--;
    830                         }
    831                         append("%%");
     922                       
     923                        APPEND("%%");
    832924                        break;
    833925                }
     926               
    834927                format++;
    835928        }
    836929       
    837         #undef append
    838         #undef recurse
    839        
    840930        return maxsize - remaining;
    841931}
    842932
    843 
    844 /** Converts a time value to a broken-down UTC time
    845  *
    846  * @param time    Time to convert
    847  * @param result  Structure to store the result to
    848  *
    849  * @return        EOK or a negative error code
     933/** 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 *
    850940 */
    851941int time_utc2tm(const time_t time, struct tm *restrict result)
    852942{
    853943        assert(result != NULL);
    854 
     944       
    855945        /* Set result to epoch. */
    856946        result->tm_sec = 0;
     
    860950        result->tm_mon = 0;
    861951        result->tm_year = 70; /* 1970 */
    862 
    863         if (_normalize_time(result, time) == -1)
     952       
     953        if (normalize_time(result, time) == -1)
    864954                return EOVERFLOW;
    865 
     955       
    866956        return EOK;
    867957}
    868958
    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 *
    877969 */
    878970int time_utc2str(const time_t time, char *restrict buf)
    879971{
    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);
    887978        return EOK;
    888979}
    889980
    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)
    894984 *
    895985 * @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 *
    898989 */
    899990void time_tm2str(const struct tm *restrict timeptr, char *restrict buf)
     
    901992        assert(timeptr != NULL);
    902993        assert(buf != NULL);
    903 
     994       
    904995        static const char *wday[] = {
    905996                "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    906997        };
     998       
    907999        static const char *mon[] = {
    9081000                "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    9091001                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    9101002        };
    911 
     1003       
    9121004        snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
    9131005            wday[timeptr->tm_wday],
     
    9181010}
    9191011
    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 *
    9281021 */
    9291022int time_local2tm(const time_t time, struct tm *restrict result)
    9301023{
    931         // TODO: deal with timezone
    932         // currently assumes system and all times are in GMT
    933 
     1024        // TODO: Deal with timezones.
     1025        //       Currently assumes system and all times are in UTC
     1026       
    9341027        /* Set result to epoch. */
    9351028        result->tm_sec = 0;
     
    9391032        result->tm_mon = 0;
    9401033        result->tm_year = 70; /* 1970 */
    941 
    942         if (_normalize_time(result, time) == -1)
     1034       
     1035        if (normalize_time(result, time) == -1)
    9431036                return EOVERFLOW;
    944 
     1037       
    9451038        return EOK;
    9461039}
    9471040
    948 /**
    949  * Converts the calendar time to a null terminated string
    950  * of the form "Wed Jun 30 21:49:08 1993\n" expressed relative to the
     1041/** 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
    9511044 * 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 *
    9581052 */
    9591053int time_local2str(const time_t time, char *buf)
    9601054{
    9611055        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       
    9671060        time_tm2str(&loctime, buf);
    968 
    9691061        return EOK;
    9701062}
    9711063
    972 /**
    973  * Calculate the difference between two times, in seconds.
    974  *
     1064/** Calculate the difference between two times, in seconds.
     1065 *
    9751066 * @param time1 First time.
    9761067 * @param time0 Second time.
    977  * @return Time in seconds.
     1068 *
     1069 * @return Time difference in seconds.
     1070 *
    9781071 */
    9791072double difftime(time_t time1, time_t time0)
  • uspace/lib/c/include/fourcc.h

    ref3da5a rb412168  
    3838#include <libarch/common.h>
    3939
     40typedef uint32_t fourcc_t;
     41
    4042#define FOURCC(a, b, c, d) \
    4143        (((UINT32_T) (a)) | (((UINT32_T) (b)) << 8) | \
  • uspace/lib/c/include/stats.h

    ref3da5a rb412168  
    4343#include <abi/sysinfo.h>
    4444
     45#define LOAD_UNIT  65536
     46
    4547extern stats_cpu_t *stats_get_cpus(size_t *);
    4648extern stats_physmem_t *stats_get_physmem(void);
    4749extern load_t *stats_get_load(size_t *);
    48 extern sysarg_t stats_get_uptime(void);
    4950
    5051extern stats_task_t *stats_get_tasks(size_t *);
  • uspace/lib/c/include/stddef.h

    ref3da5a rb412168  
    4242#endif
    4343
     44#define offsetof(type,member) ((size_t) &(((type *) 0)->member))
    4445
    4546#endif
  • uspace/lib/c/include/sys/time.h

    ref3da5a rb412168  
    4040#include <sys/types.h>
    4141
    42 #define DST_NONE 0
    43 #define ASCTIME_BUF_LEN 26
     42#define DST_NONE  0
     43#define ASCTIME_BUF_LEN  26
    4444
    4545typedef long time_t;
     
    5050
    5151struct tm {
    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. */
     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. */
    6161};
    6262
     
    7171};
    7272
    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);
     73extern void tv_add(struct timeval *, suseconds_t);
     74extern suseconds_t tv_sub(struct timeval *, struct timeval *);
     75extern int tv_gt(struct timeval *, struct timeval *);
     76extern int tv_gteq(struct timeval *, struct timeval *);
     77extern void gettimeofday(struct timeval *, struct timezone *);
     78extern void getuptime(struct timeval *);
    7979
    8080extern void udelay(useconds_t);
    8181
    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);
     82extern time_t mktime(struct tm *);
     83extern int time_utc2tm(const time_t, struct tm *);
     84extern int time_utc2str(const time_t, char *);
     85extern void time_tm2str(const struct tm *, char *);
     86extern int time_local2tm(const time_t, struct tm *);
     87extern int time_local2str(const time_t, char *);
     88extern double difftime(time_t, time_t);
     89extern size_t strftime(char *restrict, size_t, const char *restrict,
     90    const struct tm *restrict);
    9191
    9292#endif
  • uspace/lib/draw/Makefile

    ref3da5a rb412168  
    3131SLIBRARY = libdraw.so.0.0
    3232LSONAME = libdraw.so0
    33 EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX)
     33EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX) -I$(LIBCOMPRESS_PREFIX)
    3434
    3535SOURCES = \
    3636        codec/tga.c \
     37        codec/tga.gz.c \
     38        codec/webp.c \
    3739        cursor/embedded.c \
    3840        font/embedded.c \
  • uspace/lib/draw/codec/tga.c

    ref3da5a rb412168  
    110110 * @return True on succesful decoding.
    111111 * @return False on failure.
     112 *
    112113 */
    113114static bool decode_tga_header(void *data, size_t size, tga_t *tga)
     
    174175 * @return Newly allocated surface with the decoded content.
    175176 * @return NULL on error or unsupported format.
     177 *
    176178 */
    177179surface_t *decode_tga(void *data, size_t size, surface_flags_t flags)
     
    264266 * @return True on succesful encoding.
    265267 * @return False on failure.
     268 *
    266269 */
    267270bool encode_tga(surface_t *surface, void **pdata, size_t *psize)
  • uspace/lib/trackmod/Makefile

    ref3da5a rb412168  
    3232SOURCES = \
    3333        protracker.c \
    34         trackmod.c
     34        trackmod.c \
     35        xm.c
    3536
    3637include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/trackmod/protracker.c

    ref3da5a rb412168  
    113113}
    114114
     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 */
     123static 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 */
     140static 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;
     181error:
     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 */
     193static 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;
     247error:
     248        return rc;
     249}
     250
    115251/** Load protracker module.
    116252 *
     
    128264        protracker_order_list_t *order_list;
    129265        protracker_smp_t *sample;
    130         size_t nread;
    131266        size_t samples;
    132267        size_t channels;
    133268        size_t patterns;
    134         size_t cells;
    135         size_t i, j;
     269        size_t i;
     270        size_t nread;
    136271        int rc;
    137272
     
    192327        module->channels = channels;
    193328
    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) {
    197332                printf("Out of memory.\n");
    198333                rc = ENOMEM;
     
    221356        }
    222357
     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
    223363        /* 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;
    246367
    247368        /* 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;
    274372
    275373        (void) fclose(f);
     374
     375        module->def_bpm = protracker_def_bpm;
     376        module->def_tpr = protracker_def_tpr;
    276377
    277378        *rmodule = module;
  • uspace/lib/trackmod/trackmod.c

    ref3da5a rb412168  
    4040
    4141#include "macros.h"
     42#include "protracker.h"
    4243#include "trackmod.h"
     44#include "xm.h"
    4345
    4446/** Tunables */
     
    5254        base_clock = 8363 * 428,
    5355        /** Maximum sample volume */
    54         vol_max = 63,
    55         /** Default TPR */
    56         def_tpr = 6,
    57         /** Default BPM */
    58         def_bpm = 125
     56        vol_max = 64,
     57        /** Minimum period */
     58        period_min = 113,
     59        /** Maxium period */
     60        period_max = 856
    5961};
    6062
     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  */
     73static unsigned finetune_factor[16] = {
     74        10595, 10518, 10443, 10368, 10293, 10219, 10145, 10072,
     75        10000,  9928,  9857,  9786,  9715,  9645,  9576,  9507
     76};
     77
     78static 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
    6187static size_t trackmod_get_next_ord_idx(trackmod_modplay_t *);
    6288
     
    7096}
    7197
     98/** Destroy instrument.
     99 *
     100 * @param instr Intrument
     101 */
     102static 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
    72110/** Destroy pattern.
    73111 *
     
    97135
    98136        /* 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);
    103141        }
    104142
     
    114152}
    115153
     154int 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
    116167/** Return current pattern.
    117168 *
     
    137188    size_t row, size_t channel, trackmod_cell_t *cell)
    138189{
    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 */
     203static 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)
    149220 *
    150221 * @param modplay Module playback
     
    156227{
    157228        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 */
     265static 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];
    162280        chan->smp_pos = 0;
    163281        chan->lsmp = 0;
    164         chan->period = cell->period;
     282
    165283        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 */
     292static 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;
    166300}
    167301
     
    175309    uint8_t param)
    176310{
    177         modplay->chan[chan].volume = param & vol_max;
     311        modplay->chan[chan].volume = param % (vol_max + 1);
    178312}
    179313
     
    189323        size_t next_idx;
    190324        trackmod_pattern_t *next_pat;
     325        unsigned row;
     326
     327        /* Strangely the parameter is BCD */
     328        row = (param >> 4) * 10 + (param & 0xf);
    191329
    192330        next_idx = trackmod_get_next_ord_idx(modplay);
     
    194332
    195333        modplay->pat_break = true;
    196         modplay->pat_break_row = param % next_pat->rows;
     334        modplay->pat_break_row = row % next_pat->rows;
    197335}
    198336
     
    212350}
    213351
     352/** Process Fine volume slide down effect.
     353 *
     354 * @param modplay Module playback
     355 * @param chan    Channel number
     356 * @param param   Effect parameter
     357 */
     358static 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 */
     375static 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 */
     392static 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 */
     407static 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 */
     419static 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 */
     431static 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 */
     448static 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 */
     465static 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 */
     477static 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 */
     489static 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 */
     507static 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
    214538/** Process effect.
    215539 *
     
    222546{
    223547        uint8_t param8;
     548        uint8_t param4;
    224549
    225550        param8 = cell->effect & 0xff;
    226551
    227552        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;
    228565        case 0xc00:
    229566                trackmod_effect_set_volume(modplay, chan, param8);
     
    238575                break;
    239576        }
     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        }
    240594}
    241595
     
    249603    trackmod_cell_t *cell)
    250604{
    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)) {
    252610                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);
    254616        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;
    255620}
    256621
     
    267632        pattern = trackmod_cur_pattern(modplay);
    268633
     634        if (modplay->debug)
     635                printf("%02zx: ", modplay->row);
     636
    269637        for (i = 0; i < modplay->module->channels; i++) {
    270638                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
    273646                trackmod_process_cell(modplay, i, &cell);
    274647        }
     
    289662        ord_idx = modplay->ord_idx + 1;
    290663        if (ord_idx >= modplay->module->ord_list_len)
    291                 ord_idx = 0; /* XXX */
     664                ord_idx = modplay->module->restart_pos;
    292665
    293666        return ord_idx;
     
    313686}
    314687
     688/** Clear effects at end of row. */
     689static 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. */
     700static 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
    315740/** Advance to next row.
    316741 *
     
    320745{
    321746        trackmod_pattern_t *pattern;
     747
     748        /* Clear effect state at end of row */
     749        trackmod_clear_effects(modplay);
    322750
    323751        pattern = trackmod_cur_pattern(modplay);
     
    328756                trackmod_next_pattern(modplay);
    329757
     758        trackmod_process_tick(modplay);
    330759        trackmod_process_row(modplay);
    331760}
     
    341770        if (modplay->tick >= modplay->tpr)
    342771                trackmod_next_row(modplay);
     772        else
     773                trackmod_process_tick(modplay);
    343774}
    344775
     
    366797        modplay->smp = 0;
    367798
    368         modplay->tpr = def_tpr;
    369         modplay->bpm = def_bpm;
     799        modplay->tpr = module->def_tpr;
     800        modplay->bpm = module->def_bpm;
    370801
    371802        modplay->chan = calloc(module->channels,
     
    374805                goto error;
    375806
     807        trackmod_process_tick(modplay);
    376808        trackmod_process_row(modplay);
    377809
     
    416848}
    417849
     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 */
     858int 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
    418873/** Advance sample position to next frame.
    419874 *
     
    422877static void chan_smp_next_frame(trackmod_chan_t *chan)
    423878{
    424         chan->lsmp = chan->sample->data[chan->smp_pos];
     879        chan->lsmp = trackmod_sample_get_frame(chan->sample, chan->smp_pos);
    425880        ++chan->smp_pos;
    426881
    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 */
    429887                if (chan->smp_pos >= chan->sample->length) {
    430888                        chan->sample = NULL;
    431889                        chan->smp_pos = 0;
    432890                }
    433         } else {
    434                 /** Looping */
     891                break;
     892        case tl_forward_loop:
     893                /** Forward loop */
    435894                if (chan->smp_pos >= chan->sample->loop_start +
    436895                    chan->sample->loop_len) {
     
    455914        trackmod_chan_t *chan = &modplay->chan[cidx];
    456915
    457         if (chan->sample == NULL)
     916        if (chan->sample == NULL || chan->period == 0)
    458917                return 0;
    459918
     
    464923         */
    465924        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;
    468927
    469928        period = (int)chan->period;
  • uspace/lib/trackmod/trackmod.h

    ref3da5a rb412168  
    4040
    4141extern trackmod_module_t *trackmod_module_new(void);
     42extern int trackmod_module_load(char *, trackmod_module_t **);
    4243extern void trackmod_module_destroy(trackmod_module_t *);
    4344extern int trackmod_modplay_create(trackmod_module_t *, unsigned,
     
    4546extern void trackmod_modplay_destroy(trackmod_modplay_t *);
    4647extern void trackmod_modplay_get_samples(trackmod_modplay_t *, void *, size_t);
     48extern int trackmod_sample_get_frame(trackmod_sample_t *, size_t);
    4749
    4850#endif
  • uspace/lib/trackmod/types/protracker.h

    ref3da5a rb412168  
    4747        protracker_olist_len = 128,
    4848        /** 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
    5054};
    5155
  • uspace/lib/trackmod/types/trackmod.h

    ref3da5a rb412168  
    4141#include <stdint.h>
    4242
     43enum {
     44        max_key = 96,
     45        keyoff_note = 97
     46};
     47
     48typedef 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
    4357/** Sample */
    4458typedef struct {
    4559        /** Length in frames */
    4660        size_t length;
     61        /** Bytes per sample */
     62        size_t bytes_smp;
    4763        /** Sample data */
    48         int8_t *data;
     64        void *data;
     65        /** Loop type */
     66        trackmod_looptype_t loop_type;
    4967        /** Loop start position in frames */
    5068        size_t loop_start;
    51         /** Loop length in frames or 0 - no looping */
     69        /** Loop length in frames (> 0) */
    5270        size_t loop_len;
    5371        /** Default volume (0..63) */
    5472        uint8_t def_vol;
     73        /** Relative note */
     74        int rel_note;
     75        /** Finetune value (-8..7) in 1/8 semitones */
     76        int finetune;
    5577} trackmod_sample_t;
     78
     79/** Instrument */
     80typedef 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 */
     90typedef 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;
    56102
    57103/** Pattern */
     
    62108        size_t channels;
    63109        /** Pattern data */
    64         uint32_t *data;
     110        trackmod_cell_t *data;
    65111} trackmod_pattern_t;
    66112
     
    70116        size_t channels;
    71117        /** 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;
    75121        /** Number of patterns */
    76122        size_t patterns;
     
    81127        /** Order list */
    82128        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;
    83135} trackmod_module_t;
    84136
     
    92144        /** Sample position (clock ticks within frame) */
    93145        size_t smp_clk;
    94         /** Period */
     146        /** Current period */
    95147        unsigned period;
     148        /** Period after note was processed, zero if no note */
     149        unsigned period_new;
    96150        /** Volume */
    97151        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;
    98159} trackmod_chan_t;
    99160
     
    132193} trackmod_modplay_t;
    133194
    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 
    144195#endif
    145196
Note: See TracChangeset for help on using the changeset viewer.