[Kernelloader-cvs] linux/minimalistic condtest.c, NONE, 1.1 condtest.h, NONE, 1.1 createthread.S, N
Run Linux on the Playstation 2
Brought to you by:
kloader
From: Mega M. <kl...@us...> - 2014-08-26 15:55:12
|
Update of /cvsroot/kernelloader/linux/minimalistic In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv19848 Modified Files: Makefile main.c printf.c ps2devtest.c ps2sprtest.c ps2vputest.c stdio.h syscalls.S unistd.h Added Files: condtest.c condtest.h createthread.S createthread.h futex.h mman.h pthread.c pthread.h Log Message: Add test code for futex and LL/SC instructions. Implement simple pthread interface. --- NEW FILE: createthread.h --- #ifndef _CREATE_THREAD_H_ #define _CREATE_THREAD_H_ #include "unistd.h" typedef struct { void *(*start_routine) (void *); void *arg; } stack_params_t; /** Same as syscall clone, but expects that stack is set and has the content * of stack_params_t. */ pid_t create_thread(int flags, stack_params_t *stack, pid_t *parent_tid, pid_t *child_tid); #endif Index: unistd.h =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/unistd.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** unistd.h 29 Dec 2011 21:26:28 -0000 1.3 --- unistd.h 26 Aug 2014 15:55:09 -0000 1.4 *************** *** 18,25 **** --- 18,31 ---- pid_t getpid (void); + pid_t gettid (void); pid_t fork(void); + pid_t clone(int flags, void *stack, pid_t *parent_tid, pid_t *child_tid); + pid_t waitpid(pid_t pid, int *status, int options); + /** Exit current thread. */ void exit(int status); + /** Exit current process. */ + void exit_group(int status); #endif Index: syscalls.S =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/syscalls.S,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** syscalls.S 10 Aug 2013 14:32:56 -0000 1.12 --- syscalls.S 26 Aug 2014 15:55:09 -0000 1.13 *************** *** 37,43 **** --- 37,47 ---- /* process */ DEFINE_SYSCALL(getpid) + DEFINE_SYSCALL(gettid) DEFINE_SYSCALL(fork) + DEFINE_SYSCALL(clone) DEFINE_SYSCALL(nanosleep) DEFINE_SYSCALL(exit) + DEFINE_SYSCALL(exit_group) + DEFINE_SYSCALL(waitpid) /* system */ *************** *** 53,55 **** --- 57,62 ---- #ifdef __NR_rt_sigreturn DEFINE_SYSCALL(rt_sigreturn) + + /* futex */ + DEFINE_SYSCALL(futex) #endif Index: stdio.h =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/stdio.h,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** stdio.h 10 Aug 2013 14:32:56 -0000 1.8 --- stdio.h 26 Aug 2014 15:55:09 -0000 1.9 *************** *** 9,14 **** #include <asm-generic/fcntl.h> - typedef long off_t; - /* Syscalls: */ int open(const char *filename, int flags, int mode); --- 9,12 ---- *************** *** 17,22 **** int read(int fd, const char *buffer, unsigned int size); int ioctl(unsigned int fd, unsigned int cmd, void *arg); - void *mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t offset); - int munmap(void *addr, unsigned long length); int fsync(int fd); --- 15,18 ---- *************** *** 25,30 **** --- 21,30 ---- int putchar(int c); int printf(const char *format, ...); + int printf(const char *format, ...); int snprintf(char *str, int len, const char *fmt, ...); int vsnprintf(char *b, int len, const char *fmt, va_list pvar); + void set_output_device(const char *device); + void unset_output_device(void); + #endif Index: main.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/main.c,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** main.c 3 Jul 2013 20:03:54 -0000 1.27 --- main.c 26 Aug 2014 15:55:09 -0000 1.28 *************** *** 13,16 **** --- 13,17 ---- #include "ps2vputest.h" #include "ps2sprtest.h" + #include "condtest.h" #define DEVICE "/dev/ttyS0" *************** *** 429,433 **** } ! void signal_handler(int sig, siginfo_t *info, context_t *c) { int i; --- 430,434 ---- } ! static void signal_handler(int sig, siginfo_t *info, context_t *c) { int i; *************** *** 468,473 **** } ! for(;;) ! ; } --- 469,478 ---- } ! if (getpid() == 1) { ! for (;;) { ! ; /* inifinite wait. */ ! } ! } ! exit_group(-1); } *************** *** 532,537 **** if (rv != 0) { printf("close returned rv = %d\n", (uint32_t) rv); ! exit(-1); } } else { printf("Failed to open %s errno %d.\n", DEVICE, errno); --- 537,544 ---- if (rv != 0) { printf("close returned rv = %d\n", (uint32_t) rv); ! exit_group(-1); } + /* Print also to serial console. */ + set_output_device(DEVICE); } else { printf("Failed to open %s errno %d.\n", DEVICE, errno); *************** *** 652,655 **** --- 659,666 ---- printf("Release: %s\n", uts.release); printf("Version: %s\n", uts.version); + + /* Disable printing on serial console. */ + unset_output_device(); + test_atomic(); *************** *** 705,708 **** --- 716,722 ---- printf("Size of long double %u\n", sizeof(long double)); + printf("Run condtest\n"); + condtest(); + test_ps2dev(); --- NEW FILE: mman.h --- #ifndef __MMAN_H_ #define __MMAN_H_ #include <asm/mman.h> typedef long off_t; void *mmap(void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t offset); int munmap(void *addr, unsigned long length); #endif Index: Makefile =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/Makefile,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** Makefile 29 Jul 2014 20:19:16 -0000 1.21 --- Makefile 26 Aug 2014 15:55:09 -0000 1.22 *************** *** 22,27 **** -DASSEMBLER ! MODS = start syscalls main snprintf printf string stdio usleep floatingpoint \ ! signal errno atomic ps2devtest ps2vputest ps2sprtest OBJS = $(addsuffix .o, $(MODS)) --- 22,28 ---- -DASSEMBLER ! MODS = start syscalls main snprintf printf string stdio usleep floatingpoint ! MODS += signal errno atomic ps2devtest ps2vputest ps2sprtest condtest ! MODS += pthread createthread OBJS = $(addsuffix .o, $(MODS)) --- NEW FILE: condtest.h --- #ifndef _CONDTEST_H_ #define _CONDTEST_H_ int condtest(void); #endif --- NEW FILE: pthread.c --- #include "stdio.h" #include "mman.h" #include "time.h" #include "unistd.h" #include "string.h" #include "futex.h" #include "errno.h" #include "signal.h" #include "pthread.h" #include "createthread.h" #include <linux/sched.h> #include <linux/wait.h> /* Simple pthread interface which supports basic stuff like mutexes, but is * incomplete. */ #define STACK_SIZE (512 * 1024) #define STACK_OVERHEAD 16 #define assert(x) \ do { \ if (!(x)) { \ assert_fail(__FILE__, __LINE__, #x); \ } \ } while(0) /* * Try to swap values. * newval will be 0 on error. * oldval will contain old value. */ #define atomic_swap(futex, newval, oldval) \ do { \ __asm__ __volatile__( \ ".set push\n" \ ".set noreorder\n" \ ".set mips2\n" \ "ll %0, %2\n" \ "sc %1, %2\n" \ ".set pop\n" \ :"=&r"(oldval),"+r"(newval):"m"(futex)); \ } while(0) static void assert_fail(const char *file, int line, const char *assert) { printf("%s:%u: assert \"%s\" failed.\n", file, line, assert); exit_group(-1); } int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { memset(mutex, 0, sizeof(*mutex)); return 0; } int pthread_mutex_destroy(pthread_mutex_t *mutex) { return 0; } int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { memset(cond, 0, sizeof(*cond)); return 0; } int pthread_cond_destroy(pthread_cond_t *cond) { return 0; } static int swapvalue(int *mem, int newval) { int oldval; int rv; do { rv = newval; atomic_swap(*mem, rv, oldval); } while(rv == 0); return oldval; } int pthread_mutex_lock(pthread_mutex_t *mutex) { if (mutex->futex == 2) { futex(&mutex->futex, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 2, NULL, NULL, 0); } while (swapvalue(&mutex->futex, 2) != 0) { futex(&mutex->futex, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 2, NULL, NULL, 0); } return 0; } int pthread_mutex_unlock(pthread_mutex_t *mutex) { int oldval; oldval = swapvalue(&mutex->futex, 0); if (oldval > 1) { futex(&mutex->futex, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1, NULL, NULL, 0); } return 0; } int pthread_cond_signal(pthread_cond_t *cond) { return 0; } int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { int rv; rv = pthread_mutex_unlock(mutex); assert(rv == 0); usleep(20000); // TBD: Wait for real signal rv = pthread_mutex_lock(mutex); assert(rv == 0); return 0; } int pthread_join(pthread_t thread, void **retval) { usleep(20000); // TBD: Implement pthread_join(). /* Free stack. */ /* TBD: THis can cause page faults when thread wasn't really * terminated. */ if (thread.stack != ((void *) -1)) { munmap(thread.stack, STACK_SIZE); } return 0; } void pthread_exit(void *retval) { exit((int) retval); } int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { int rv; void *stack; stack_params_t *stack_params; stack = mmap(NULL, STACK_SIZE, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_GROWSDOWN|MAP_ANONYMOUS, -1, 0); if (stack == (void *) -1) { return -1; } if (thread != NULL) { thread->stack = stack; } stack += STACK_SIZE; stack -= STACK_OVERHEAD; /* The function prepare_thread will read these values: */ stack_params = stack; stack_params->start_routine = start_routine; stack_params->arg = arg; rv = create_thread(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD |CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID |CLONE_CHILD_CLEARTID, stack_params, NULL, NULL); if (thread != NULL) { thread->tid = rv; } if (rv != -1) { rv = 0; } return rv; } Index: ps2sprtest.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/ps2sprtest.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** ps2sprtest.c 10 Aug 2013 15:10:57 -0000 1.2 --- ps2sprtest.c 26 Aug 2014 15:55:09 -0000 1.3 *************** *** 1,3 **** --- 1,4 ---- #include "stdio.h" + #include "mman.h" #include "ps2sprtest.h" #include "errno.h" *************** *** 24,28 **** /* Address must be page aligned and SPR_SIZE aligned. */ ! buffer = mmap(MAP_ADDR, SPR_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == ((void *) -1)) { printf("test_ps2spr: Failed to map " PS2_DEV_SPR ", errno = %d.\n", errno); --- 25,29 ---- /* Address must be page aligned and SPR_SIZE aligned. */ ! buffer = mmap((void *) MAP_ADDR, SPR_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == ((void *) -1)) { printf("test_ps2spr: Failed to map " PS2_DEV_SPR ", errno = %d.\n", errno); Index: ps2vputest.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/ps2vputest.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** ps2vputest.c 6 May 2014 22:51:32 -0000 1.2 --- ps2vputest.c 26 Aug 2014 15:55:09 -0000 1.3 *************** *** 1,3 **** --- 1,4 ---- #include "stdio.h" + #include "mman.h" #include "ps2vputest.h" #include "errno.h" --- NEW FILE: condtest.c --- #include "stdio.h" #include "mman.h" #include "time.h" #include "unistd.h" #include "string.h" #include "futex.h" #include "errno.h" #include "signal.h" #include "pthread.h" #include <linux/sched.h> #include <linux/wait.h> #define TEST_SIZE 4096 #define MAX_TESTS 100 #define assert(x) \ do { \ if (!(x)) { \ assert_fail(__FILE__, __LINE__, #x); \ } \ } while(0) #define do_sc(futex, newval) \ do { \ __asm__ __volatile__( \ ".set push\n" \ ".set noreorder\n" \ ".set mips2\n" \ "sc %0, %1\n" \ ".set pop\n" \ :"+r"(newval):"m"(futex)); \ } while(0) static pthread_cond_t cond; static pthread_mutex_t mutex; static pthread_t cthread; static pthread_t pthread; static volatile int pstate = 0; static volatile int cstate = 0; static volatile unsigned int counter; static volatile unsigned int consumed; static pid_t maintid = 0; static volatile const char *file_g; static volatile int line_g; static volatile const char *assert_g; static volatile int sc_slow_mem_result; static void assert_fail(const char *file, int line, const char *assert) { if (maintid == gettid()) { printf("%s:%u: assert \"%s\" failed.\n", file, line, assert); exit_group(-1); } file_g = file; line_g = line; assert_g = assert; while(1) { usleep(1000000); } } void *producer_thread(void *arg) { int rv; register long sp asm("$sp"); (void) arg; pstate = __LINE__; printf("TID %d: producer_thread stack 0x%08lx\n", gettid(), sp); pstate = __LINE__; while(counter < MAX_TESTS) { if (consumed == counter) { pstate = __LINE__; rv = pthread_mutex_lock(&mutex); pstate = __LINE__; assert(rv == 0); /* Wait until consumer_thread is running. */ while(cstate == 0) { usleep(20000); } pstate = __LINE__; if (consumed == counter) { counter++; } pstate = __LINE__; rv = pthread_cond_signal(&cond); pstate = __LINE__; assert(rv == 0); pstate = __LINE__; rv = pthread_mutex_unlock(&mutex); pstate = __LINE__; assert(rv == 0); } else { pstate = __LINE__; } } pstate = __LINE__; pthread_exit(NULL); return NULL; } void *consumer_thread(void *arg) { int rv; register long sp asm("$sp"); (void) arg; cstate = __LINE__; printf("TID %d: consumer_thread stack 0x%08lx\n", gettid(), sp); cstate = __LINE__; rv = pthread_mutex_lock(&mutex); cstate = __LINE__; assert(rv == 0); while(consumed < MAX_TESTS) { cstate = __LINE__; rv = pthread_cond_wait(&cond, &mutex); cstate = __LINE__; assert(rv == 0); //assert((consumed + 1) == counter); // TBD: Implement pthread_cond_wait() if (counter != consumed) { cstate = __LINE__; printf("TID %d: counter %u\n", gettid(), counter); cstate = __LINE__; consumed = counter; cstate = __LINE__; } } cstate = __LINE__; rv = pthread_mutex_unlock(&mutex); assert(rv == 0); cstate = __LINE__; pthread_exit(NULL); return NULL; } /* Test a bug when pthread_cond_wait() is not woken. */ void cond_test(void) { int rv; unsigned int prev_counter; int c; counter = 0; rv = pthread_mutex_init(&mutex, NULL); assert(rv == 0); rv = pthread_cond_init(&cond, NULL); assert(rv == 0); rv = pthread_create(&pthread, NULL, producer_thread, NULL); assert(rv == 0); /* Wait until producer_thread is running. */ while(pstate == 0) { usleep(20000); } rv = pthread_create(&cthread, NULL, consumer_thread, NULL); assert(rv == 0); prev_counter = counter; c = 0; while (consumed < MAX_TESTS) { if (counter == prev_counter) { c++; if ((c & 15) == 15) { printf("Error detected: pstate line %u cstate line %u\n", pstate, cstate); } } else { c = 0; } prev_counter = counter; usleep(10000); if (assert_g != NULL) { printf("%s:%u: assert \"%s\" failed.\n", file_g, line_g, assert_g); exit_group(-1); } } rv = pthread_join(pthread, NULL); assert(rv == 0); rv = pthread_join(cthread, NULL); assert(rv == 0); rv = pthread_mutex_destroy(&mutex); assert(rv == 0); rv = pthread_cond_destroy(&cond); assert(rv == 0); } static void sc_signal_handler(int sig, siginfo_t *info, context_t *c) { int i; printf("Received signal %d\n", sig); if (info->si_code != 0x80) { printf("Code 0x%08x no from kernel\n", info->si_code); } switch (sig) { case SIGSEGV: case SIGILL: case SIGFPE: case SIGBUS: case SIGTRAP: printf("Fault addr 0x%08x\n", (unsigned int) info->si_addr); default: break; } printf("EIP 0x%08x\n", (unsigned int) c->uc_mcontext.sc_pc); /* Print registers: */ for (i = 0; i < 32; i++) { switch (i & 7) { case 7: printf("0x%08x\n", (unsigned int) c->uc_mcontext.sc_regs[i]); break; case 0: if (i < 10) { printf(" %d: ", i); } else { printf("%d: ", i); } default: printf("0x%08x ", (unsigned int) c->uc_mcontext.sc_regs[i]); break; } } sc_slow_mem_result = 1; /* Jump over problematic instruction. */ c->uc_mcontext.sc_pc += 4; } void test_slow_memory(void) { int *futex = NULL; int newval = 0; struct sigaction sa; struct sigaction oldsa; sc_slow_mem_result = 0; memset(&oldsa, 0, sizeof(oldsa)); /* Install signal handler to be able to test segmentation faults. */ memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = sc_signal_handler; sa.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &sa, &oldsa); printf("test sc instruction with slow memory.\n"); futex = mmap(NULL, TEST_SIZE, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_GROWSDOWN|MAP_ANONYMOUS, -1, 0); if (futex == ((void *) -1)) { printf("Out of memory.\n"); return; } do_sc(*futex, newval); /* Restore old signal handler. */ sigaction(SIGSEGV, &oldsa, NULL); if (sc_slow_mem_result) { printf("Success\n"); } else { /* TBD: The sc instruction should cause a segmentation fault * when memory is slow, e.g. swapped out. */ printf("*** FAIL ***\n"); usleep(1000000); } munmap(futex, TEST_SIZE); } /** * Code for testing mutexes, conditin variables and the LL/SC instructions. */ int condtest(void) { maintid = gettid(); test_slow_memory(); printf("pthread_cond_wait() test program maintid %d.\n", maintid); cond_test(); return 0; } Index: ps2devtest.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/ps2devtest.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** ps2devtest.c 10 Aug 2013 15:10:57 -0000 1.3 --- ps2devtest.c 26 Aug 2014 15:55:09 -0000 1.4 *************** *** 1,3 **** --- 1,4 ---- #include "stdio.h" + #include "mman.h" #include "ps2devtest.h" #include "errno.h" *************** *** 177,181 **** } ! buffer = mmap(0, BUFFERSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == ((void *) -1)) { printf("test_ps2mem: Failed to map " PS2_DEV_MEM ", errno = %d.\n", errno); --- 178,182 ---- } ! buffer = mmap(NULL, BUFFERSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == ((void *) -1)) { printf("test_ps2mem: Failed to map " PS2_DEV_MEM ", errno = %d.\n", errno); *************** *** 192,196 **** } ! buffer = mmap(MAP_ADDR, BUFFERSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == ((void *) -1)) { printf("test_ps2mem: Failed to map " PS2_DEV_SPR ", errno = %d.\n", errno); --- 193,197 ---- } ! buffer = mmap((void *) MAP_ADDR, BUFFERSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == ((void *) -1)) { printf("test_ps2mem: Failed to map " PS2_DEV_SPR ", errno = %d.\n", errno); --- NEW FILE: createthread.S --- #include "registers.h" .text .global create_thread .ent create_thread create_thread: addiu sp,sp,-8 sw ra,4(sp) # Syscall clone la t9, clone jalr t9 beq v0, zero, prepare_thread lw ra,4(sp) addiu sp,sp,8 j ra # Thread created with new stack prepare_thread: # Get function to call from stack: lw t9, 0(sp) lw a0, 4(sp) jalr t9 # Pass return value to syscall exit: add a0, zero, v0 la t9, exit jalr t9 loop: b loop .end create_thread --- NEW FILE: pthread.h --- #ifndef _PTHREAD_H_ #define _PTHREAD_H_ /* Simple pthread interface which supports basic stuff like mutexes, but is * incomplete. * Some stuff is not working, because it is incomplete. */ typedef struct { pid_t tid; void *stack; } pthread_t; typedef struct { } pthread_attr_t; typedef struct { int futex; } pthread_mutex_t; typedef struct { } pthread_mutexattr_t; typedef struct { } pthread_condattr_t; typedef struct { } pthread_cond_t; int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond); int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_join(pthread_t thread, void **retval); void pthread_exit(void *retval); int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); #endif Index: printf.c =================================================================== RCS file: /cvsroot/kernelloader/linux/minimalistic/printf.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** printf.c 10 Aug 2013 14:56:09 -0000 1.3 --- printf.c 26 Aug 2014 15:55:09 -0000 1.4 *************** *** 6,10 **** #define MAX_BUFFER 256 ! #define DEVICE "/dev/ttyS0" int printf(const char *format, ...) --- 6,30 ---- #define MAX_BUFFER 256 ! static int fdout = -1; ! static int initialized = 0; ! ! void set_output_device(const char *device) ! { ! if (!initialized) { ! fdout = open(device, O_WRONLY, 0); ! initialized = 1; ! } ! } ! ! void unset_output_device(void) ! { ! if (initialized) { ! if (fdout >= 0) { ! close(fdout); ! fdout = -1; ! } ! initialized = 0; ! } ! } int printf(const char *format, ...) *************** *** 14,29 **** va_list varg; va_start(varg, format); - static int fd = 0; - static int initialized = 0; - - if (!initialized) { - fd = open(DEVICE, O_WRONLY, 0); - initialized = 1; - } ret = vsnprintf(buffer, MAX_BUFFER, format, varg); ! write(STDOUT_FILENO, buffer, ret); ! if (fd >= 0) { ! write(fd, buffer, ret); ! fsync(fd); } va_end(varg); --- 34,42 ---- va_list varg; va_start(varg, format); ret = vsnprintf(buffer, MAX_BUFFER, format, varg); ! write(STDERR_FILENO, buffer, ret); ! if (fdout >= 0) { ! write(fdout, buffer, ret); ! fsync(fdout); } va_end(varg); --- NEW FILE: futex.h --- #ifndef _FUTEX_H_ #define _FUTEX_H_ #include "linux/futex.h" int futex(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3); #endif |