Changes in uspace/lib/c/generic/io/log.c [14de4106:9d58539] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/log.c
r14de4106 r9d58539 38 38 #include <stdlib.h> 39 39 #include <stdio.h> 40 #include <async.h> 40 41 41 #include <io/log.h> 42 #include <ipc/logger.h>43 #include <ns.h>44 42 45 /** Log messages are printed under this name. */ 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 46 51 static const char *log_prog_name; 47 52 48 /** IPC session with the logger service. */ 49 static async_sess_t *logger_session; 50 51 /** Maximum length of a single log message (in bytes). */ 52 #define MESSAGE_BUFFER_SIZE 4096 53 54 FIBRIL_RWLOCK_INITIALIZE(current_observed_level_lock); 55 log_level_t current_observed_level; 56 57 static int logger_register(async_sess_t *session, const char *prog_name) 58 { 59 async_exch_t *exchange = async_exchange_begin(session); 60 if (exchange == NULL) { 61 return ENOMEM; 62 } 63 64 aid_t reg_msg = async_send_0(exchange, LOGGER_REGISTER, NULL); 65 int rc = async_data_write_start(exchange, prog_name, str_size(prog_name)); 66 sysarg_t reg_msg_rc; 67 async_wait_for(reg_msg, ®_msg_rc); 68 69 async_exchange_end(exchange); 70 71 if (rc != EOK) { 72 return rc; 73 } 74 75 return reg_msg_rc; 76 } 77 78 static int logger_message(async_sess_t *session, log_level_t level, const char *message) 79 { 80 async_exch_t *exchange = async_exchange_begin(session); 81 if (exchange == NULL) { 82 return ENOMEM; 83 } 84 85 aid_t reg_msg = async_send_1(exchange, LOGGER_MESSAGE, level, NULL); 86 int rc = async_data_write_start(exchange, message, str_size(message)); 87 sysarg_t reg_msg_rc; 88 async_wait_for(reg_msg, ®_msg_rc); 89 90 async_exchange_end(exchange); 91 92 /* 93 * Getting ENAK means no-one wants our message. That is not an 94 * error at all. 95 */ 96 if (rc == ENAK) 97 rc = EOK; 98 99 if (rc != EOK) { 100 return rc; 101 } 102 103 return reg_msg_rc; 104 } 105 106 static void cannot_use_level_changed_monitor(void) 107 { 108 fibril_rwlock_write_lock(¤t_observed_level_lock); 109 current_observed_level = LVL_LIMIT; 110 fibril_rwlock_write_unlock(¤t_observed_level_lock); 111 } 112 113 static int observed_level_changed_monitor(void *arg) 114 { 115 async_sess_t *monitor_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_SINK, 0); 116 if (monitor_session == NULL) { 117 cannot_use_level_changed_monitor(); 118 return ENOMEM; 119 } 120 121 int rc = logger_register(monitor_session, log_prog_name); 122 if (rc != EOK) { 123 cannot_use_level_changed_monitor(); 124 return rc; 125 } 126 127 async_exch_t *exchange = async_exchange_begin(monitor_session); 128 if (exchange == NULL) { 129 cannot_use_level_changed_monitor(); 130 return ENOMEM; 131 } 132 133 while (true) { 134 sysarg_t has_reader; 135 sysarg_t msg_rc = async_req_0_1(exchange, 136 LOGGER_BLOCK_UNTIL_READER_CHANGED, &has_reader); 137 if (msg_rc != EOK) { 138 cannot_use_level_changed_monitor(); 139 break; 140 } 141 142 fibril_rwlock_write_lock(¤t_observed_level_lock); 143 if ((bool) has_reader) { 144 current_observed_level = LVL_LIMIT; 145 } else { 146 current_observed_level = LVL_NOTE; 147 } 148 fibril_rwlock_write_unlock(¤t_observed_level_lock); 149 } 150 151 async_exchange_end(exchange); 152 153 return EOK; 154 } 155 156 static log_level_t get_current_observed_level(void) 157 { 158 fibril_rwlock_read_lock(¤t_observed_level_lock); 159 log_level_t level = current_observed_level; 160 fibril_rwlock_read_unlock(¤t_observed_level_lock); 161 return level; 162 } 53 /** Prefixes for individual logging levels. */ 54 static 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" 61 }; 163 62 164 63 /** Initialize the logging system. … … 170 69 { 171 70 assert(level < LVL_LIMIT); 71 log_level = level; 172 72 73 log_stream = stdout; 173 74 log_prog_name = str_dup(prog_name); 174 75 if (log_prog_name == NULL) 175 76 return ENOMEM; 176 77 177 logger_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_SINK, 0); 178 if (logger_session == NULL) { 179 return ENOMEM; 180 } 181 182 int rc = logger_register(logger_session, log_prog_name); 183 184 current_observed_level = LVL_NOTE; 185 186 fid_t observed_level_changed_fibril = fibril_create(observed_level_changed_monitor, NULL); 187 if (observed_level_changed_fibril == 0) { 188 cannot_use_level_changed_monitor(); 189 } else { 190 fibril_add_ready(observed_level_changed_fibril); 191 } 192 193 return rc; 194 } 195 196 bool __log_shall_record(log_level_t level) 197 { 198 return get_current_observed_level() >= level; 78 return EOK; 199 79 } 200 80 … … 206 86 * @param fmt Format string (no traling newline). 207 87 */ 208 void __log_msg(log_level_t level, const char *fmt, ...)88 void log_msg(log_level_t level, const char *fmt, ...) 209 89 { 210 90 va_list args; 211 91 212 92 va_start(args, fmt); 213 __log_msgv(level, fmt, args);93 log_msgv(level, fmt, args); 214 94 va_end(args); 215 95 } … … 222 102 * @param fmt Format string (no trailing newline) 223 103 */ 224 void __log_msgv(log_level_t level, const char *fmt, va_list args)104 void log_msgv(log_level_t level, const char *fmt, va_list args) 225 105 { 226 106 assert(level < LVL_LIMIT); 227 107 228 if (get_current_observed_level() < level) { 229 return; 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); 230 119 } 231 232 char *message_buffer = malloc(MESSAGE_BUFFER_SIZE);233 if (message_buffer == NULL) {234 return;235 }236 237 vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);238 logger_message(logger_session, level, message_buffer);239 120 } 240 121
Note:
See TracChangeset
for help on using the changeset viewer.