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

Changes in / [13c4fe0:dc5aa568] in mainline


Ignore:
Files:
14 added
15 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r13c4fe0 rdc5aa568  
    7474        $(USPACE_PATH)/srv/locsrv/locsrv \
    7575        $(USPACE_PATH)/srv/bd/rd/rd \
    76         $(USPACE_PATH)/srv/vfs/vfs
     76        $(USPACE_PATH)/srv/vfs/vfs \
     77        $(USPACE_PATH)/srv/logger/logger
    7778
    7879ifeq ($(RDFMT),tmpfs)
     
    165166        $(USPACE_PATH)/app/killall/killall \
    166167        $(USPACE_PATH)/app/loc/loc \
     168        $(USPACE_PATH)/app/logset/logset \
    167169        $(USPACE_PATH)/app/mkfat/mkfat \
    168170        $(USPACE_PATH)/app/mkexfat/mkexfat \
  • kernel/genarch/include/multiboot/multiboot.h

    r13c4fe0 rdc5aa568  
    9999
    100100extern void multiboot_extract_command(char *, size_t, const char *);
     101extern void multiboot_extract_argument(char *, size_t, const char *);
    101102extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
    102103
  • kernel/genarch/src/multiboot/multiboot.c

    r13c4fe0 rdc5aa568  
    7171}
    7272
     73/** Extract arguments from the multiboot module command line.
     74 *
     75 * @param buf      Destination buffer (will be always NULL-terminated).
     76 * @param size     Size of destination buffer (in bytes).
     77 * @param cmd_line Input string (the command line).
     78 *
     79 */
     80void multiboot_extract_argument(char *buf, size_t size, const char *cmd_line)
     81{
     82        /* Start after first space. */
     83        const char *start = str_chr(cmd_line, ' ');
     84        if (start == NULL) {
     85                str_cpy(buf, size, "");
     86                return;
     87        }
     88
     89        const char *end = cmd_line + str_size(cmd_line);
     90
     91        /* Skip the space(s). */
     92        while (start != end) {
     93                if (start[0] == ' ')
     94                        start++;
     95                else
     96                        break;
     97        }
     98
     99        str_ncpy(buf, size, start, (size_t) (end - start));
     100}
     101
    73102static void multiboot_modules(uint32_t count, multiboot_module_t *mods)
    74103{
     
    84113                        multiboot_extract_command(init.tasks[init.cnt].name,
    85114                            CONFIG_TASK_NAME_BUFLEN, MULTIBOOT_PTR(mods[i].string));
    86                 } else
     115                        multiboot_extract_argument(init.tasks[init.cnt].arguments,
     116                            CONFIG_TASK_ARGUMENTS_BUFLEN, MULTIBOOT_PTR(mods[i].string));
     117                } else {
    87118                        init.tasks[init.cnt].name[0] = 0;
     119                        init.tasks[init.cnt].arguments[0] = 0;
     120                }
    88121               
    89122                init.cnt++;
  • kernel/genarch/src/multiboot/multiboot2.c

    r13c4fe0 rdc5aa568  
    4949                multiboot_extract_command(init.tasks[init.cnt].name,
    5050                    CONFIG_TASK_NAME_BUFLEN, module->string);
     51                multiboot_extract_argument(init.tasks[init.cnt].arguments,
     52                    CONFIG_TASK_ARGUMENTS_BUFLEN, module->string);
    5153               
    5254                init.cnt++;
  • kernel/generic/include/config.h

    r13c4fe0 rdc5aa568  
    4747#define CONFIG_INIT_TASKS        32
    4848#define CONFIG_TASK_NAME_BUFLEN  32
     49#define CONFIG_TASK_ARGUMENTS_BUFLEN 64
    4950
    5051#ifndef __ASM__
     
    5657        size_t size;
    5758        char name[CONFIG_TASK_NAME_BUFLEN];
     59        char arguments[CONFIG_TASK_ARGUMENTS_BUFLEN];
    5860} init_task_t;
    5961
  • kernel/generic/src/main/kinit.c

    r13c4fe0 rdc5aa568  
    6969#include <str.h>
    7070#include <sysinfo/stats.h>
     71#include <sysinfo/sysinfo.h>
    7172#include <align.h>
    7273
     
    179180        program_t programs[CONFIG_INIT_TASKS];
    180181       
     182        // FIXME: do not propagate arguments through sysinfo
     183        // but pass them directly to the tasks
     184        for (i = 0; i < init.cnt; i++) {
     185                const char *arguments = init.tasks[i].arguments;
     186                if (str_length(arguments) == 0)
     187                        continue;
     188                if (str_length(init.tasks[i].name) == 0)
     189                        continue;
     190                size_t arguments_size = str_size(arguments);
     191
     192                void *arguments_copy = malloc(arguments_size, 0);
     193                if (arguments_copy == NULL)
     194                        continue;
     195                memcpy(arguments_copy, arguments, arguments_size);
     196
     197                char item_name[CONFIG_TASK_NAME_BUFLEN + 15];
     198                snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15,
     199                    "init_args.%s", init.tasks[i].name);
     200
     201                sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size);
     202        }
     203
    181204        for (i = 0; i < init.cnt; i++) {
    182205                if (init.tasks[i].paddr % FRAME_SIZE) {
  • uspace/Makefile

    r13c4fe0 rdc5aa568  
    4747        app/klog \
    4848        app/loc \
     49        app/logset \
    4950        app/mkfat \
    5051        app/mkexfat \
     
    7475        srv/clipboard \
    7576        srv/locsrv \
     77        srv/logger \
    7678        srv/devman \
    7779        srv/loader \
  • uspace/app/tester/Makefile

    r13c4fe0 rdc5aa568  
    4545        stdio/stdio1.c \
    4646        stdio/stdio2.c \
     47        stdio/logger1.c \
     48        stdio/logger2.c \
    4749        fault/fault1.c \
    4850        fault/fault2.c \
  • uspace/app/tester/tester.c

    r13c4fe0 rdc5aa568  
    3939#include <stdio.h>
    4040#include <str.h>
     41#include <io/log.h>
    4142#include "tester.h"
    4243
     
    5556#include "stdio/stdio1.def"
    5657#include "stdio/stdio2.def"
     58#include "stdio/logger1.def"
     59#include "stdio/logger2.def"
    5760#include "fault/fault1.def"
    5861#include "fault/fault2.def"
     
    138141        }
    139142       
     143        log_init("tester", LVL_NOTE);
     144
    140145        test_quiet = false;
    141146        test_argc = argc - 2;
  • uspace/app/tester/tester.h

    r13c4fe0 rdc5aa568  
    8888extern const char *test_stdio1(void);
    8989extern const char *test_stdio2(void);
     90extern const char *test_logger1(void);
     91extern const char *test_logger2(void);
    9092extern const char *test_fault1(void);
    9193extern const char *test_fault2(void);
  • uspace/lib/c/Makefile

    r13c4fe0 rdc5aa568  
    9797        generic/io/printf.c \
    9898        generic/io/log.c \
     99        generic/io/logctl.c \
    99100        generic/io/klog.c \
    100101        generic/io/snprintf.c \
  • uspace/lib/c/generic/io/log.c

    r13c4fe0 rdc5aa568  
    3838#include <stdlib.h>
    3939#include <stdio.h>
    40 
     40#include <async.h>
    4141#include <io/log.h>
    42 
    43 /** Serialization mutex for logging functions. */
    44 static FIBRIL_MUTEX_INITIALIZE(log_serializer);
    45 
    46 /** Current log level. */
    47 static log_level_t log_level;
    48 
    49 static FILE *log_stream;
    50 
     42#include <ipc/logger.h>
     43#include <ns.h>
     44
     45/** Log messages are printed under this name. */
    5146static const char *log_prog_name;
    5247
    53 /** Prefixes for individual logging levels. */
    5448static const char *log_level_names[] = {
    55         [LVL_FATAL] = "Fatal error",
    56         [LVL_ERROR] = "Error",
    57         [LVL_WARN] = "Warning",
    58         [LVL_NOTE] = "Note",
    59         [LVL_DEBUG] = "Debug",
    60         [LVL_DEBUG2] = "Debug2"
     49        "fatal",
     50        "error",
     51        "warn",
     52        "note",
     53        "debug",
     54        "debug2",
     55        NULL
    6156};
     57
     58/** IPC session with the logger service. */
     59static async_sess_t *logger_session;
     60
     61/** Maximum length of a single log message (in bytes). */
     62#define MESSAGE_BUFFER_SIZE 4096
     63
     64FIBRIL_RWLOCK_INITIALIZE(current_observed_level_lock);
     65log_level_t current_observed_level;
     66
     67static int logger_register(async_sess_t *session, const char *prog_name)
     68{
     69        async_exch_t *exchange = async_exchange_begin(session);
     70        if (exchange == NULL) {
     71                return ENOMEM;
     72        }
     73
     74        aid_t reg_msg = async_send_0(exchange, LOGGER_REGISTER, NULL);
     75        int rc = async_data_write_start(exchange, prog_name, str_size(prog_name));
     76        sysarg_t reg_msg_rc;
     77        async_wait_for(reg_msg, &reg_msg_rc);
     78
     79        async_exchange_end(exchange);
     80
     81        if (rc != EOK) {
     82                return rc;
     83        }
     84
     85        return reg_msg_rc;
     86}
     87
     88static int logger_message(async_sess_t *session, log_context_t ctx, log_level_t level, const char *message)
     89{
     90        async_exch_t *exchange = async_exchange_begin(session);
     91        if (exchange == NULL) {
     92                return ENOMEM;
     93        }
     94
     95        aid_t reg_msg = async_send_2(exchange, LOGGER_MESSAGE,
     96            ctx, level, NULL);
     97        int rc = async_data_write_start(exchange, message, str_size(message));
     98        sysarg_t reg_msg_rc;
     99        async_wait_for(reg_msg, &reg_msg_rc);
     100
     101        async_exchange_end(exchange);
     102
     103        /*
     104         * Getting ENAK means no-one wants our message. That is not an
     105         * error at all.
     106         */
     107        if (rc == ENAK)
     108                rc = EOK;
     109
     110        if (rc != EOK) {
     111                return rc;
     112        }
     113
     114        return reg_msg_rc;
     115}
     116
     117static void cannot_use_level_changed_monitor(void)
     118{
     119        fibril_rwlock_write_lock(&current_observed_level_lock);
     120        current_observed_level = LVL_LIMIT;
     121        fibril_rwlock_write_unlock(&current_observed_level_lock);
     122}
     123
     124static int observed_level_changed_monitor(void *arg)
     125{
     126        async_sess_t *monitor_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_SINK, 0);
     127        if (monitor_session == NULL) {
     128                cannot_use_level_changed_monitor();
     129                return ENOMEM;
     130        }
     131
     132        int rc = logger_register(monitor_session, log_prog_name);
     133        if (rc != EOK) {
     134                cannot_use_level_changed_monitor();
     135                return rc;
     136        }
     137
     138        async_exch_t *exchange = async_exchange_begin(monitor_session);
     139        if (exchange == NULL) {
     140                cannot_use_level_changed_monitor();
     141                return ENOMEM;
     142        }
     143
     144        while (true) {
     145                sysarg_t has_reader;
     146                sysarg_t msg_rc = async_req_0_1(exchange,
     147                    LOGGER_BLOCK_UNTIL_READER_CHANGED, &has_reader);
     148                if (msg_rc != EOK) {
     149                        cannot_use_level_changed_monitor();
     150                        break;
     151                }
     152
     153                fibril_rwlock_write_lock(&current_observed_level_lock);
     154                if ((bool) has_reader) {
     155                        current_observed_level = LVL_LIMIT;
     156                } else {
     157                        current_observed_level = LVL_NOTE;
     158                }
     159                fibril_rwlock_write_unlock(&current_observed_level_lock);
     160        }
     161
     162        async_exchange_end(exchange);
     163
     164        return EOK;
     165}
     166
     167static log_level_t get_current_observed_level(void)
     168{
     169        fibril_rwlock_read_lock(&current_observed_level_lock);
     170        log_level_t level = current_observed_level;
     171        fibril_rwlock_read_unlock(&current_observed_level_lock);
     172        return level;
     173}
     174
     175const char *log_level_str(log_level_t level)
     176{
     177        if (level >= LVL_LIMIT)
     178                return "unknown";
     179        else
     180                return log_level_names[level];
     181}
     182
     183int log_level_from_str(const char *name, log_level_t *level_out)
     184{
     185        log_level_t level = LVL_FATAL;
     186
     187        while (log_level_names[level] != NULL) {
     188                if (str_cmp(name, log_level_names[level]) == 0) {
     189                        if (level_out != NULL)
     190                                *level_out = level;
     191                        return EOK;
     192                }
     193                level++;
     194        }
     195
     196        /* Maybe user specified number directly. */
     197        char *end_ptr;
     198        int level_int = strtol(name, &end_ptr, 0);
     199        if ((end_ptr == name) || (str_length(end_ptr) != 0))
     200                return EINVAL;
     201        if (level_int < 0)
     202                return ERANGE;
     203        if (level_int >= (int) LVL_LIMIT)
     204                return ERANGE;
     205
     206        if (level_out != NULL)
     207                *level_out = (log_level_t) level_int;
     208
     209        return EOK;
     210}
    62211
    63212/** Initialize the logging system.
     
    69218{
    70219        assert(level < LVL_LIMIT);
    71         log_level = level;
    72 
    73         log_stream = stdout;
     220
    74221        log_prog_name = str_dup(prog_name);
    75222        if (log_prog_name == NULL)
    76223                return ENOMEM;
    77224
    78         return EOK;
     225        logger_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_SINK, 0);
     226        if (logger_session == NULL) {
     227                return ENOMEM;
     228        }
     229
     230        int rc = logger_register(logger_session, log_prog_name);
     231
     232        current_observed_level = LVL_NOTE;
     233
     234        fid_t observed_level_changed_fibril = fibril_create(observed_level_changed_monitor, NULL);
     235        if (observed_level_changed_fibril == 0) {
     236                cannot_use_level_changed_monitor();
     237        } else {
     238                fibril_add_ready(observed_level_changed_fibril);
     239        }
     240
     241        return rc;
     242}
     243
     244/** Create logging context.
     245 *
     246 * This function always returns a valid context.
     247 */
     248log_context_t log_context_create(const char *name)
     249{
     250        async_exch_t *exchange = async_exchange_begin(logger_session);
     251        if (exchange == NULL)
     252                return LOG_CONTEXT_DEFAULT;
     253
     254        ipc_call_t answer;
     255        aid_t reg_msg = async_send_0(exchange, LOGGER_CREATE_CONTEXT, &answer);
     256        int rc = async_data_write_start(exchange, name, str_size(name));
     257        sysarg_t reg_msg_rc;
     258        async_wait_for(reg_msg, &reg_msg_rc);
     259
     260        async_exchange_end(exchange);
     261
     262        if ((rc != EOK) || (reg_msg_rc != EOK))
     263                return LOG_CONTEXT_DEFAULT;
     264
     265        return IPC_GET_ARG1(answer);
     266}
     267
     268bool _log_shall_record(log_context_t context, log_level_t level)
     269{
     270        return get_current_observed_level() >= level;
    79271}
    80272
     
    86278 * @param fmt           Format string (no traling newline).
    87279 */
    88 void log_msg(log_level_t level, const char *fmt, ...)
     280void _log_ctx_msg(log_context_t ctx, log_level_t level, const char *fmt, ...)
    89281{
    90282        va_list args;
    91283
    92284        va_start(args, fmt);
    93         log_msgv(level, fmt, args);
     285        _log_ctx_msgv(ctx, level, fmt, args);
    94286        va_end(args);
    95287}
     
    102294 * @param fmt           Format string (no trailing newline)
    103295 */
    104 void log_msgv(log_level_t level, const char *fmt, va_list args)
     296void _log_ctx_msgv(log_context_t ctx, log_level_t level, const char *fmt, va_list args)
    105297{
    106298        assert(level < LVL_LIMIT);
    107299
    108         /* Higher number means higher verbosity. */
    109         if (level <= log_level) {
    110                 fibril_mutex_lock(&log_serializer);
    111 
    112                 fprintf(log_stream, "%s: %s: ", log_prog_name,
    113                     log_level_names[level]);
    114                 vfprintf(log_stream, fmt, args);
    115                 fputc('\n', log_stream);
    116                 fflush(log_stream);
    117 
    118                 fibril_mutex_unlock(&log_serializer);
    119         }
     300        if (get_current_observed_level() < level) {
     301                return;
     302        }
     303
     304        char *message_buffer = malloc(MESSAGE_BUFFER_SIZE);
     305        if (message_buffer == NULL) {
     306                return;
     307        }
     308
     309        vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);
     310        logger_message(logger_session, ctx, level, message_buffer);
    120311}
    121312
  • uspace/lib/c/include/io/log.h

    r13c4fe0 rdc5aa568  
    3636
    3737#include <stdarg.h>
     38#include <inttypes.h>
     39#include <bool.h>
    3840
    3941typedef enum {
     
    4951} log_level_t;
    5052
     53typedef sysarg_t log_context_t;
     54#define PRIlogctx PRIxn
     55#define LOG_CONTEXT_DEFAULT 0
     56
     57extern const char *log_level_str(log_level_t);
     58extern int log_level_from_str(const char *, log_level_t *);
     59
     60extern bool _log_shall_record(log_context_t, log_level_t);
    5161extern int log_init(const char *, log_level_t);
    52 extern void log_msg(log_level_t, const char *, ...);
    53 extern void log_msgv(log_level_t, const char *, va_list);
     62
     63extern log_context_t log_context_create(const char *);
     64
     65#define log_ctx_msg(context, level, format, ...) \
     66        do { \
     67                if (_log_shall_record((context), (level))) { \
     68                        _log_ctx_msg((context), (level), format, ##__VA_ARGS__); \
     69                } \
     70        } while (false)
     71
     72#define log_ctx_msgv(context, level, format, args) \
     73        do { \
     74                if (_log_shall_record((context), (level))) { \
     75                        _log_ctx_msgv((context), (level), format, args); \
     76                } \
     77        } while (false)
     78
     79#define log_msg(level, format, ...) \
     80        log_ctx_msg(LOG_CONTEXT_DEFAULT, (level), (format), ##__VA_ARGS__)
     81#define log_msgv(level, format, args) \
     82        log_ctx_msgv(LOG_CONTEXT_DEFAULT, (level), (format), (args))
     83
     84extern void _log_ctx_msg(log_context_t, log_level_t, const char *, ...);
     85extern void _log_ctx_msgv(log_context_t, log_level_t, const char *, va_list);
    5486
    5587#endif
  • uspace/lib/c/include/ipc/services.h

    r13c4fe0 rdc5aa568  
    4545        SERVICE_VFS        = FOURCC('v', 'f', 's', ' '),
    4646        SERVICE_LOC        = FOURCC('l', 'o', 'c', ' '),
     47        SERVICE_LOGGER     = FOURCC('l', 'o', 'g', 'g'),
    4748        SERVICE_DEVMAN     = FOURCC('d', 'e', 'v', 'n'),
    4849        SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
  • uspace/lib/usb/src/debug.c

    r13c4fe0 rdc5aa568  
    7474                }
    7575        }
     76        log_init(message_prefix, LVL_DEBUG);
    7677}
    7778
     
    148149        }
    149150
     151        va_start(args, format);
     152        log_msgv(level, format, args);
     153        va_end(args);
     154
    150155        fibril_mutex_unlock(&log_serializer);
    151156}
Note: See TracChangeset for help on using the changeset viewer.