00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <l4/util/util.h>
00030 #include <l4/sys/ipc.h>
00031 #include <l4/sys/syscalls.h>
00032 #include <l4/sys/kdebug.h>
00033 #include <l4/rmgr/librmgr.h>
00034 #if CONFIG_USE_SERIAL
00035 #include <l4/serial/serial.h>
00036 #endif
00037 #include <assert.h>
00038
00039 #include <l4/log/l4log.h>
00040 #include <stdio.h>
00041 #include <errno.h>
00042 #include "config.h"
00043 #include "tcpip.h"
00044 #include "flusher.h"
00045 #include "stuff.h"
00046
00047 #if CONFIG_USE_TCPIP==0
00048 const unsigned client_socket=0;
00049 #endif
00050
00051 int flusher_prio;
00052 l4_threadid_t main_thread, flusher_thread;
00053
00054
00055 static l4_threadid_t flush_requester;
00056
00057
00058
00059
00060
00061
00062 static int wait_for_flush_request(void){
00063 int err;
00064 l4_msgdope_t result;
00065 l4_umword_t dw0, dw1;
00066
00067 err = l4_ipc_wait(&flush_requester, NULL, &dw0, &dw1,
00068 L4_IPC_NEVER, &result);
00069 LOGd(CONFIG_LOG_IPC, "received ipc, err=%#x", err);
00070 return err;
00071 }
00072
00073
00074 static int answer_flush_request(void){
00075 int err;
00076 l4_msgdope_t result;
00077
00078 do{err = l4_ipc_send(flush_requester, NULL, 0, 0,
00079 L4_IPC_NEVER, &result);
00080 }while(err == L4_IPC_SECANCELED);
00081 return err;
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static void thread_loop(void){
00098 l4_msgdope_t result;
00099 int ret=0, err;
00100
00101
00102 rmgr_set_prio(l4_myself(), flusher_prio);
00103
00104 #if CONFIG_USE_TCPIP
00105 if(flush_to_net && (ret=net_init(0,0))!=0){
00106 LOG_Error("Error %#x initializing network", ret);
00107 }
00108 #endif
00109
00110 do{
00111 err = l4_ipc_send(main_thread, NULL, ret, 0,
00112 L4_IPC_NEVER, &result);
00113 } while(err==L4_IPC_SECANCELED);
00114 if(err){
00115 LOG_Error("sending ipc to main thread returned error %#x.", err);
00116 enter_kdebug("and now?");
00117 }
00118
00119
00120 while(1){
00121 #if CONFIG_USE_TCPIP
00122 if(flush_to_net){
00123 err = net_wait_for_client();
00124 if(err){
00125 LOG_Error("Error %#x waiting for next client.", err);
00126 l4_sleep(1000);
00127 continue;
00128 }
00129
00130 }
00131 #endif
00132
00133
00134
00135
00136 do{
00137 err = wait_for_flush_request();
00138 if(err & L4_IPC_RECANCELED){
00139
00140 LOGd(CONFIG_LOG_IPC,
00141 "Probably got interrupt, try to read from network");
00142
00143
00144 #if CONFIG_USE_TCPIP
00145 if(flush_to_net){
00146 if((err=net_receive_check())!=0){
00147 LOGd(CONFIG_LOG_TCPIP,
00148 "net_receive_check() returned error %#x", err);
00149 break;
00150 }
00151 }
00152 #endif
00153 } else if(err){
00154 LOG_Error("Error %#x receiving IPC from main-thread", err);
00155 continue;
00156 } else {
00157
00158
00159 do_flush_buffer();
00160
00161 err = answer_flush_request();
00162 if(err){
00163 LOG_Error("Error anwering flush-request.");
00164 }
00165 }
00166 } while (!flush_to_net || client_socket);
00167 }
00168
00169 LOG_Error("Log-TCP-Srv-thread: How did I get here?");
00170 enter_kdebug("Something went really wrong.");
00171 }
00172
00173 static int general_flush_buffer(int head, int(*flush)(const char*, int)){
00174 int err;
00175
00176 if(head < buffer_tail){
00177 LOGd(CONFIG_LOG_RINGBUFFER, "flushing 1/2 %d+%d",
00178 buffer_tail, buffer_size-buffer_tail);
00179 if((err=flush(buffer_array+buffer_tail,
00180 (int)buffer_size-buffer_tail))!=0) return err;
00181 LOGd(CONFIG_LOG_RINGBUFFER, "flushing 2/2 %d+%d",
00182 0, head);
00183 if((err=flush(buffer_array, head))!=0) return err;
00184 } else {
00185 LOGd(CONFIG_LOG_RINGBUFFER, "flushing 1/1 %d+%d",
00186 buffer_tail, head-buffer_tail);
00187 err = flush(buffer_array+buffer_tail, head-buffer_tail);
00188 }
00189 return err;
00190 }
00191
00192
00193
00194
00195
00196 static int console_flush(const char*addr, int size){
00197 while(*addr && size--){
00198 outchar(*addr++);
00199 }
00200 return 0;
00201 }
00202
00203 #if CONFIG_USE_SERIAL
00204 int serial_flush(const char*addr, int size){
00205 while(*addr && size--){
00206 int err;
00207 err = l4serial_outstring(addr, 1);
00208 if(err) printf("\nl4serial_outstring(): %d\n", err);
00209 if(*addr=='\n') l4serial_outstring("\r", 1);
00210 addr++;
00211 }
00212 return 0;
00213 }
00214 #endif
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 int do_flush_buffer(void){
00225 unsigned head = buffer_head;
00226 int err;
00227
00228 LOGd(CONFIG_LOG_RINGBUFFER, "Flushing buffer now.");
00229
00230 if(flush_local){
00231 err = general_flush_buffer(head, console_flush);
00232 if(err) return err;
00233 }
00234 #if CONFIG_USE_SERIAL
00235 if(flush_serial){
00236 err = general_flush_buffer(head, serial_flush);
00237 if(err) return err;
00238 }
00239 #endif
00240 #if CONFIG_USE_TCPIP
00241 if(flush_to_net){
00242 err = general_flush_buffer(head, net_flush_buffer);
00243 if(err) return err;
00244 }
00245 #endif
00246 buffer_tail = head;
00247 return 0;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 int flush_buffer(void){
00260 l4_msgdope_t result;
00261 l4_umword_t dw0, dw1;
00262 int err;
00263
00264 if(buffer_size){
00265 err = L4_IPC_SECANCELED;
00266 while(err == L4_IPC_SECANCELED){
00267 err = l4_ipc_call(flusher_thread, NULL, 0, 0,
00268 NULL, &dw0, &dw1,
00269 L4_IPC_NEVER, &result);
00270 }
00271 while(err == L4_IPC_RECANCELED){
00272 err = l4_ipc_receive(flusher_thread, NULL, &dw0, &dw1,
00273 L4_IPC_NEVER, &result);
00274 }
00275
00276 if(err){
00277 LOG_Error("Calling the flusher thread returned %#x.", err);
00278 return err;
00279 }
00280 return dw0;
00281 } else {
00282 return 0;
00283 }
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 static void flush_signaller(void){
00295
00296
00297
00298
00299
00300
00301
00302
00303 rmgr_set_prio(l4_myself(), 2);
00304 while(1){
00305 if(buffer_head!=buffer_tail){
00306 flush_buffer();
00307 }
00308 l4_sleep(100);
00309 }
00310 }
00311
00312 #if CONFIG_USE_SERIAL
00313 static void serial_esc_fn(void){
00314 int err;
00315
00316 while(1){
00317 err = l4serial_readbyte();
00318 if(err == '\e') enter_kdebug("ESC on serial");
00319 }
00320 }
00321 #endif
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 int flusher_init(void){
00333 l4_msgdope_t result;
00334 l4_umword_t dw0, dw1;
00335 int err;
00336
00337 main_thread = l4_myself();
00338
00339
00340 err = thread_create(thread_loop, &flusher_thread, "log.flush");
00341 if(err<0){
00342 LOG_Error("Error %#x creating acceptor thread.", err);
00343 goto error;
00344 }
00345 do{
00346 err = l4_ipc_receive(flusher_thread, NULL, &dw0, &dw1,
00347 L4_IPC_NEVER, &result);
00348 } while(err == L4_IPC_RECANCELED);
00349 if(err){
00350 LOG_Error("Error %#x receiving up-and-running IPC from tcpip-thread.",
00351 err);
00352 goto error;
00353 }
00354 if(dw0!=0){
00355 err = dw0;
00356 goto error;
00357 }
00358
00359 #if CONFIG_USE_SERIAL
00360 if(flush_serial){
00361 err = l4serial_init(MAXTHREADS+1, flush_serial);
00362 if(err){
00363 LOG_Error("Error %#x setting up the serial handler.", err);
00364 goto error;
00365 }
00366 if(serial_esc){
00367 l4_threadid_t dummy_t;
00368 err = thread_create(serial_esc_fn, &dummy_t, "log.serialesc");
00369 if(err<0){
00370 LOG_Error("Error %#x creating serial-esc thread", err);
00371 goto error;
00372 }
00373 }
00374 }
00375 #endif
00376
00377 err = thread_create(flush_signaller, NULL, "log.flushsig");
00378 if(err){
00379 LOG_Error("Error %#x creating flush-signaller thread.", err);
00380 goto error;
00381 }
00382
00383 return 0;
00384
00385 error:
00386 return err;
00387 }
00388