Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3684 → Rev 4377

/branches/tracing/uspace/lib/libc/include/ddi.h
37,9 → 37,11
 
#include <task.h>
 
extern int physmem_map(void *pf, void *vp, unsigned long pages, int flags);
extern int iospace_enable(task_id_t id, void *ioaddr, unsigned long size);
extern int preemption_control(int enable);
extern int device_assign_devno(void);
extern int physmem_map(void *, void *, unsigned long, int);
extern int iospace_enable(task_id_t, void *, unsigned long);
extern int preemption_control(int);
extern int pio_enable(void *, size_t, void **);
 
#endif
 
/branches/tracing/uspace/lib/libc/include/console.h
0,0 → 1,65
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_H_
#define LIBC_CONSOLE_H_
 
#include <console/style.h>
#include <console/color.h>
#include <sys/types.h>
#include <bool.h>
 
extern int console_open(bool);
extern void console_close(void);
extern void console_wait(void);
 
extern void console_clear(void);
extern void console_goto(int, int);
extern void console_putchar(wchar_t);
extern ssize_t console_write(const char *, size_t);
extern void console_putstr(const char *);
extern void console_flush(void);
 
extern int console_get_size(int *, int *);
extern void console_set_style(int);
extern void console_set_color(int, int, int);
extern void console_set_rgb_color(int, int);
extern void console_cursor_visibility(int);
 
extern void console_kcon_enable(void);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/string.h
35,32 → 35,60
#ifndef LIBC_STRING_H_
#define LIBC_STRING_H_
 
#include <mem.h>
#include <sys/types.h>
#include <bool.h>
 
#define bzero(ptr, len) memset((ptr), 0, (len))
#define U_SPECIAL '?'
#define U_BOM 0xfeff
 
extern void * memset(void *, int, size_t);
extern void * memcpy(void *, const void *, size_t);
extern void * memmove(void *, const void *, size_t);
/** No size limit constant */
#define STR_NO_LIMIT ((size_t) -1)
 
extern int bcmp(const char *, const char *, size_t);
/** Maximum size of a string containing @c length characters */
#define STR_BOUNDS(length) ((length) << 2)
 
extern int strcmp(const char *, const char *);
extern int strncmp(const char *, const char *, size_t);
extern int stricmp(const char *, const char *);
extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
 
extern char *strcpy(char *, const char *);
extern char *strncpy(char *, const char *, size_t);
extern size_t str_size(const char *str);
extern size_t wstr_size(const wchar_t *str);
 
extern char *strcat(char *, const char *);
extern size_t str_lsize(const char *str, count_t max_len);
extern size_t wstr_lsize(const wchar_t *str, count_t max_len);
 
extern size_t strlen(const char *);
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
 
extern char *strdup(const char *);
extern count_t str_nlength(const char *str, size_t size);
extern count_t wstr_nlength(const wchar_t *str, size_t size);
 
extern char *strchr(const char *, int);
extern char *strrchr(const char *, int);
extern bool ascii_check(wchar_t ch);
extern bool chr_check(wchar_t ch);
 
extern int str_cmp(const char *s1, const char *s2);
extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
 
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
extern void str_append(char *dest, size_t size, const char *src);
 
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
 
extern const char *str_chr(const char *str, wchar_t ch);
extern const char *str_rchr(const char *str, wchar_t ch);
 
extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
extern bool wstr_remove(wchar_t *str, count_t pos);
 
extern char *str_dup(const char *);
 
/*
* TODO: Get rid of this.
*/
 
extern int stricmp(const char *, const char *);
 
extern long int strtol(const char *, char **, int);
extern unsigned long strtoul(const char *, char **, int);
 
/branches/tracing/uspace/lib/libc/include/vfs/vfs.h
39,7 → 39,8
 
extern char *absolutize(const char *, size_t *);
 
extern int mount(const char *, const char *, const char *);
extern int mount(const char *, const char *, const char *, const char *,
const unsigned int flags);
 
#endif
 
/branches/tracing/uspace/lib/libc/include/async.h
76,7 → 76,7
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (dataptr))
 
extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr);
extern aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
86,8 → 86,8
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
suseconds_t timeout);
 
fid_t async_new_connection(ipcarg_t in_phone_hash,ipc_callid_t callid,
ipc_call_t *call, void (*cthread)(ipc_callid_t,ipc_call_t *));
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
void async_usleep(suseconds_t timeout);
void async_create_manager(void);
void async_destroy_manager(void);
98,27 → 98,27
 
/* Wrappers for simple communication */
#define async_msg_0(phone, method) \
ipc_call_async_0((phone), (method), NULL, NULL, !in_interrupt_handler())
ipc_call_async_0((phone), (method), NULL, NULL, true)
#define async_msg_1(phone, method, arg1) \
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
!in_interrupt_handler())
true)
#define async_msg_2(phone, method, arg1, arg2) \
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
!in_interrupt_handler())
true)
#define async_msg_3(phone, method, arg1, arg2, arg3) \
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
!in_interrupt_handler())
true)
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, !in_interrupt_handler())
NULL, true)
#define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, !in_interrupt_handler())
(arg5), NULL, NULL, true)
 
/*
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros
* are in the form async_req_m_n(), where m is the number of payload arguments
* and n is the number of return arguments. The macros decidce between the fast
* and n is the number of return arguments. The macros decide between the fast
* and slow verion based on m.
*/
#define async_req_0_0(phoneid, method) \
253,8 → 253,6
fibril_dec_sercount();
}
 
extern bool in_interrupt_handler(void);
 
extern atomic_t async_futex;
 
#endif
/branches/tracing/uspace/lib/libc/include/stdio.h
49,17 → 49,31
int n; \
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \
if (n > 0) \
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, strlen(buf)); \
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, str_size(buf)); \
}
 
typedef struct {
/** Underlying file descriptor. */
int fd;
 
/** Error indicator. */
int error;
 
/** End-of-file indicator. */
int eof;
} FILE;
 
extern FILE *stdin, *stdout, *stderr;
 
extern int getchar(void);
 
extern int puts(const char *);
extern int putchar(int);
extern int fflush(FILE *);
 
extern int printf(const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *fmt, ...);
extern int sprintf(char *, const char *, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int vprintf(const char *, va_list);
66,11 → 80,35
extern int vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__)
 
extern int rename(const char *, const char *);
 
extern FILE *fopen(const char *, const char *);
extern int fclose(FILE *);
extern size_t fread(void *, size_t, size_t, FILE *);
extern size_t fwrite(const void *, size_t, size_t, FILE *);
extern int feof(FILE *);
extern int ferror(FILE *);
extern void clearerr(FILE *);
 
extern int fgetc(FILE *);
extern int fputc(int, FILE *);
extern int fputs(const char *, FILE *);
 
extern int fprintf(FILE *, const char *, ...);
extern int vfprintf(FILE *, const char *, va_list);
 
#define getc fgetc
#define putc fputc
 
extern int fseek(FILE *, long, int);
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/task.h
40,6 → 40,7
typedef uint64_t task_id_t;
 
extern task_id_t task_get_id(void);
extern int task_set_name(const char *name);
extern task_id_t task_spawn(const char *path, char *const argv[]);
 
#endif
/branches/tracing/uspace/lib/libc/include/unistd.h
44,9 → 44,11
 
#define getpagesize() (PAGE_SIZE)
 
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
extern ssize_t write(int, const void *, size_t);
extern ssize_t read(int, void *, size_t);
58,7 → 60,7
extern int chdir(const char *);
extern char *getcwd(char *buf, size_t);
 
extern void _exit(int status);
extern void _exit(int status) __attribute__ ((noreturn));
extern void *sbrk(ssize_t incr);
extern int usleep(unsigned long usec);
extern unsigned int sleep(unsigned int seconds);
/branches/tracing/uspace/lib/libc/include/thread.h
45,7 → 45,7
extern void __thread_main(uspace_arg_t *);
 
extern int thread_create(void (*)(void *), void *, char *, thread_id_t *);
extern void thread_exit(int);
extern void thread_exit(int) __attribute__ ((noreturn));
extern void thread_detach(thread_id_t);
extern int thread_join(thread_id_t);
extern thread_id_t thread_get_id(void);
/branches/tracing/uspace/lib/libc/include/kbd/kbd.h
0,0 → 1,65
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_KBD_H_
#define LIBC_KBD_H_
 
#include <sys/types.h>
 
typedef enum kbd_ev_type {
KE_PRESS,
KE_RELEASE
} kbd_ev_type_t;
 
/** Keyboard event structure. */
typedef struct {
/** Press or release event. */
kbd_ev_type_t type;
 
/** Keycode of the key that was pressed or released. */
unsigned int key;
 
/** Bitmask of modifiers held. */
unsigned int mods;
 
/** The character that was generated or '\0' for none. */
wchar_t c;
} kbd_event_t;
 
extern int kbd_get_event(kbd_event_t *);
 
#endif
/** @}
*/
/branches/tracing/uspace/lib/libc/include/kbd/keycode.h
0,0 → 1,220
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_KBD_KEYCODE_H_
#define LIBC_KBD_KEYCODE_H_
 
/** Keycode definitions.
*
* A keycode identifies a key by its position on the keyboard, rather
* than by its label. For human readability, key positions are noted
* with the key label on a keyboard with US layout. This label has
* nothing to do with the character, that the key produces
* -- this is determined by the keymap.
*
* The keyboard model reflects a standard PC keyboard layout.
* Non-standard keyboards need to be mapped to this model in some
* logical way. Scancodes are mapped to keycodes with a scanmap.
*
* For easier mapping to the model and to emphasize the nature of keycodes,
* they really are organized here by position, rather than by label.
*/
enum keycode {
 
/* Main block row 1 */
 
KC_BACKTICK = 1,
 
KC_1,
KC_2,
KC_3,
KC_4,
KC_5,
KC_6,
KC_7,
KC_8,
KC_9,
KC_0,
 
KC_MINUS,
KC_EQUALS,
KC_BACKSPACE,
 
/* Main block row 2 */
 
KC_TAB,
 
KC_Q,
KC_W,
KC_E,
KC_R,
KC_T,
KC_Y,
KC_U,
KC_I,
KC_O,
KC_P,
 
KC_LBRACKET,
KC_RBRACKET,
 
/* Main block row 3 */
 
KC_CAPS_LOCK,
KC_A,
KC_S,
KC_D,
KC_F,
KC_G,
KC_H,
KC_J,
KC_K,
KC_L,
 
KC_SEMICOLON,
KC_QUOTE,
KC_BACKSLASH,
 
KC_ENTER,
 
/* Main block row 4 */
 
KC_LSHIFT,
 
KC_Z,
KC_X,
KC_C,
KC_V,
KC_B,
KC_N,
KC_M,
 
KC_COMMA,
KC_PERIOD,
KC_SLASH,
 
KC_RSHIFT,
 
/* Main block row 5 */
 
KC_LCTRL,
KC_LALT,
KC_SPACE,
KC_RALT,
KC_RCTRL,
 
/* Function keys block */
 
KC_ESCAPE,
 
KC_F1,
KC_F2,
KC_F3,
KC_F4,
KC_F5,
KC_F6,
KC_F7,
KC_F8,
KC_F9,
KC_F10,
KC_F11,
KC_F12,
 
KC_PRTSCR,
KC_SCROLL_LOCK,
KC_PAUSE,
 
/* Cursor keys block */
 
KC_INSERT,
KC_HOME,
KC_PAGE_UP,
 
KC_DELETE,
KC_END,
KC_PAGE_DOWN,
 
KC_UP,
KC_LEFT,
KC_DOWN,
KC_RIGHT,
 
/* Numeric block */
 
KC_NUM_LOCK,
KC_NSLASH,
KC_NTIMES,
KC_NMINUS,
 
KC_NPLUS,
KC_NENTER,
 
KC_N7,
KC_N8,
KC_N9,
 
KC_N4,
KC_N5,
KC_N6,
 
KC_N1,
KC_N2,
KC_N3,
 
KC_N0,
KC_NPERIOD
} keycode_t;
 
enum keymod {
KM_LSHIFT = 0x001,
KM_RSHIFT = 0x002,
KM_LCTRL = 0x004,
KM_RCTRL = 0x008,
KM_LALT = 0x010,
KM_RALT = 0x020,
KM_CAPS_LOCK = 0x040,
KM_NUM_LOCK = 0x080,
KM_SCROLL_LOCK = 0x100,
 
KM_SHIFT = KM_LSHIFT | KM_RSHIFT,
KM_CTRL = KM_LCTRL | KM_RCTRL,
KM_ALT = KM_LALT | KM_RALT
} keymod_t;
 
#endif
/** @}
*/
/branches/tracing/uspace/lib/libc/include/console/color.h
0,0 → 1,55
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_COLOR_H_
#define LIBC_CONSOLE_COLOR_H_
 
enum console_color {
COLOR_BLACK = 0,
COLOR_BLUE = 1,
COLOR_GREEN = 2,
COLOR_CYAN = 3,
COLOR_RED = 4,
COLOR_MAGENTA = 5,
COLOR_YELLOW = 6,
COLOR_WHITE = 7,
 
CATTR_BRIGHT = 8,
CATTR_BLINK = 8
};
 
#endif
/** @}
*/
/branches/tracing/uspace/lib/libc/include/console/style.h
0,0 → 1,46
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_STYLE_H_
#define LIBC_CONSOLE_STYLE_H_
 
enum console_style {
STYLE_NORMAL = 0,
STYLE_EMPHASIS = 1
};
 
#endif
/** @}
*/
/branches/tracing/uspace/lib/libc/include/mem.h
0,0 → 1,51
/*
* Copyright (c) 2005 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_MEM_H_
#define LIBC_MEM_H_
 
#include <sys/types.h>
 
#define bzero(ptr, len) memset((ptr), 0, (len))
 
extern void * memset(void *, int, size_t);
extern void * memcpy(void *, const void *, size_t);
extern void * memmove(void *, const void *, size_t);
 
extern int bcmp(const char *, const char *, size_t);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/loader/loader.h
44,7 → 44,8
int phone_id;
} loader_t;
 
extern loader_t *loader_spawn(char *name);
extern int loader_spawn(const char *);
extern loader_t *loader_connect(void);
extern int loader_get_task_id(loader_t *, task_id_t *);
extern int loader_set_pathname(loader_t *, const char *);
extern int loader_set_args(loader_t *, char *const []);
/branches/tracing/uspace/lib/libc/include/io/printf_core.h
39,16 → 39,19
#include <stdarg.h>
 
/** Structure for specifying output methods for different printf clones. */
struct printf_spec {
/* Output function, returns count of printed characters or EOF */
int (*write)(void *, size_t, void *);
/* Support data - output stream specification, its state, locks,... */
typedef struct printf_spec {
/* String output function, returns number of printed characters or EOF */
int (*str_write)(const char *, size_t, void *);
/* Wide string output function, returns number of printed characters or EOF */
int (*wstr_write)(const wchar_t *, size_t, void *);
/* User data - output stream specification, state, locks, etc. */
void *data;
} printf_spec_t;
 
};
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap);
 
int printf_core(const char *fmt, struct printf_spec *ps ,va_list ap);
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/io/stream.h
37,18 → 37,12
 
#include <libarch/types.h>
 
#define EMFILE -17
#define EMFILE -17
 
extern void open_console(void);
extern void close_console(void);
extern ssize_t read_stdin(void *, size_t);
extern int klog_puts(const char *);
extern void klog_update(void);
 
extern ssize_t read_stdin(void *, size_t);
extern ssize_t write_stdout(const void *, size_t);
extern ssize_t write_stderr(const void *, size_t);
 
extern int get_cons_phone(void);
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/event.h
0,0 → 1,46
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_EVENT_H_
#define LIBC_EVENT_H_
 
#include <kernel/ipc/event_types.h>
#include <ipc/ipc.h>
 
extern int event_subscribe(event_type_t, ipcarg_t);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/macros.h
0,0 → 1,50
/*
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_MACROS_H_
#define LIBC_MACROS_H_
 
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/ipc/bus.h
0,0 → 1,47
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libcipc
* @{
*/
/** @file
*/
 
#ifndef LIBC_BUS_H_
#define LIBC_BUS_H_
 
#include <ipc/ipc.h>
 
typedef enum {
BUS_CLEAR_INTERRUPT = IPC_FIRST_USER_METHOD
} bus_request_t;
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/ipc/ipc.h
47,8 → 47,7
} ipc_call_t;
typedef sysarg_t ipc_callid_t;
 
typedef void (* ipc_async_callback_t)(void *private, int retval,
ipc_call_t *data);
typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *);
 
/*
* User-friendly wrappers for ipc_call_sync_fast() and ipc_call_sync_slow().
173,22 → 172,20
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
(arg4), (arg5), (res1), (res2), (res3), (res4), (res5))
 
extern int ipc_call_sync_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2,
ipcarg_t *result3, ipcarg_t *result4, ipcarg_t *result5);
extern int ipc_call_sync_fast(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *);
 
extern int ipc_call_sync_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5,
ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3, ipcarg_t *result4,
ipcarg_t *result5);
extern int ipc_call_sync_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, ipcarg_t *, ipcarg_t *, ipcarg_t *, ipcarg_t *,
ipcarg_t *);
 
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags);
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *data, uint32_t usec);
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int);
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t);
static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data)
{
return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
}
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data);
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *);
 
/*
* User-friendly wrappers for ipc_answer_fast() and ipc_answer_slow().
209,10 → 206,10
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \
ipc_answer_slow((callid), (retval), (arg1), (arg2), (arg3), (arg4), (arg5))
 
extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval,
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4);
extern ipcarg_t ipc_answer_slow(ipc_callid_t callid, ipcarg_t retval,
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5);
extern ipcarg_t ipc_answer_fast(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t);
extern ipcarg_t ipc_answer_slow(ipc_callid_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, ipcarg_t);
 
/*
* User-friendly wrappers for ipc_call_async_fast() and ipc_call_async_slow().
220,8 → 217,7
* arguments. The macros decide between the fast and the slow version according
* to m.
*/
#define ipc_call_async_0(phoneid, method, private, callback, \
can_preempt) \
#define ipc_call_async_0(phoneid, method, private, callback, can_preempt) \
ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \
(callback), (can_preempt))
#define ipc_call_async_1(phoneid, method, arg1, private, callback, \
245,23 → 241,24
ipc_call_async_slow((phoneid), (method), (arg1), (arg2), (arg3), \
(arg4), (arg5), (private), (callback), (can_preempt))
 
extern void ipc_call_async_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, void *private,
ipc_async_callback_t callback, int can_preempt);
extern void ipc_call_async_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, void *private,
ipc_async_callback_t callback, int can_preempt);
extern void ipc_call_async_fast(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, void *, ipc_async_callback_t, int);
extern void ipc_call_async_slow(int, ipcarg_t, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, void *, ipc_async_callback_t, int);
 
extern int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3,
ipcarg_t *phone);
extern int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3);
extern int ipc_hangup(int phoneid);
extern int ipc_register_irq(int inr, int devno, int method, irq_code_t *code);
extern int ipc_unregister_irq(int inr, int devno);
extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method,
ipcarg_t arg1, ipcarg_t arg2, int mode);
#define IPC_FLAG_BLOCKING 0x01
 
extern int ipc_connect_to_me(int, int, int, int, ipcarg_t *);
extern int ipc_connect_me_to(int, int, int, int);
extern int ipc_connect_me_to_blocking(int, int, int, int);
extern int ipc_hangup(int);
extern int ipc_register_irq(int, int, int, irq_code_t *);
extern int ipc_unregister_irq(int, int);
extern int ipc_forward_fast(ipc_callid_t, int, int, ipcarg_t, ipcarg_t, int);
extern int ipc_forward_slow(ipc_callid_t, int, int, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t, ipcarg_t, int);
 
 
/*
* User-friendly wrappers for ipc_share_in_start().
*/
274,24 → 271,22
#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
 
extern int ipc_share_in_start(int phoneid, void *dst, size_t size, ipcarg_t arg,
int *flags);
extern int ipc_share_in_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags);
extern int ipc_share_out_start(int phoneid, void *src, int flags);
extern int ipc_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags);
extern int ipc_share_out_finalize(ipc_callid_t callid, void *dst);
extern int ipc_data_read_start(int phoneid, void *dst, size_t size);
extern int ipc_data_read_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_data_read_finalize(ipc_callid_t callid, const void *src,
size_t size);
extern int ipc_data_write_start(int phoneid, const void *src, size_t size);
extern int ipc_data_write_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size);
extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *);
extern int ipc_share_in_receive(ipc_callid_t *, size_t *);
extern int ipc_share_in_finalize(ipc_callid_t, void *, int );
extern int ipc_share_out_start(int, void *, int);
extern int ipc_share_out_receive(ipc_callid_t *, size_t *, int *);
extern int ipc_share_out_finalize(ipc_callid_t, void *);
extern int ipc_data_read_start(int, void *, size_t);
extern int ipc_data_read_receive(ipc_callid_t *, size_t *);
extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t);
extern int ipc_data_write_start(int, const void *, size_t);
extern int ipc_data_write_receive(ipc_callid_t *, size_t *);
extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t);
 
#include <task.h>
 
extern int ipc_connect_kbox(task_id_t id);
extern int ipc_connect_kbox(task_id_t);
 
#endif
 
/branches/tracing/uspace/lib/libc/include/ipc/console.h
0,0 → 1,58
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libcipc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IPC_CONSOLE_H_
#define LIBC_IPC_CONSOLE_H_
 
#include <ipc/ipc.h>
 
typedef enum {
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD,
CONSOLE_PUTCHAR,
CONSOLE_WRITE,
CONSOLE_CLEAR,
CONSOLE_GOTO,
CONSOLE_GETSIZE,
CONSOLE_FLUSH,
CONSOLE_SET_STYLE,
CONSOLE_SET_COLOR,
CONSOLE_SET_RGB_COLOR,
CONSOLE_CURSOR_VISIBILITY,
CONSOLE_KCON_ENABLE
} console_request_t;
 
#endif
/** @}
*/
/branches/tracing/uspace/lib/libc/include/ipc/services.h
30,8 → 30,8
* @{
*/
/**
* @file services.h
* @brief List of all known services and their codes.
* @file services.h
* @brief List of all known services and their codes.
*/
 
#ifndef LIBIPC_SERVICES_H_
38,12 → 38,15
#define LIBIPC_SERVICES_H_
 
typedef enum {
SERVICE_PCI = 1,
SERVICE_LOAD = 1,
SERVICE_PCI,
SERVICE_KEYBOARD,
SERVICE_VIDEO,
SERVICE_CONSOLE,
SERVICE_VFS,
SERVICE_DEVMAP
SERVICE_DEVMAP,
SERVICE_FHC,
SERVICE_OBIO
} services_t;
 
/* Memory area to be received from NS */
/branches/tracing/uspace/lib/libc/include/ipc/fb.h
48,10 → 48,11
FB_VIEWPORT_CREATE,
FB_VIEWPORT_DELETE,
FB_SET_STYLE,
FB_SET_COLOR,
FB_SET_RGB_COLOR,
FB_GET_RESOLUTION,
FB_DRAW_TEXT_DATA,
FB_FLUSH,
FB_VIEWPORT_DB,
FB_DRAW_PPM,
FB_PREPARE_SHM,
FB_DROP_SHM,
59,7 → 60,6
FB_VP_DRAW_PIXMAP,
FB_VP2PIXMAP,
FB_DROP_PIXMAP,
FB_TRANS_PUTCHAR,
FB_ANIM_CREATE,
FB_ANIM_DROP,
FB_ANIM_ADDPIXMAP,
66,10 → 66,11
FB_ANIM_CHGVP,
FB_ANIM_START,
FB_ANIM_STOP,
FB_POINTER_MOVE
FB_POINTER_MOVE,
FB_SCREEN_YIELD,
FB_SCREEN_RECLAIM
} fb_request_t;
 
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/errno.h
35,6 → 35,10
#ifndef LIBC_ERRNO_H_
#define LIBC_ERRNO_H_
 
/* TODO: support threads/fibrils */
extern int _errno;
#define errno _errno
 
#include <kernel/errno.h>
 
#define ENAMETOOLONG (-256)
/branches/tracing/uspace/lib/libc/include/sys/types.h
37,11 → 37,15
 
#include <libarch/types.h>
 
typedef unsigned long size_t;
typedef signed long ssize_t;
typedef long off_t;
typedef int mode_t;
 
typedef int32_t wchar_t;
 
typedef volatile uint8_t ioport8_t;
typedef volatile uint16_t ioport16_t;
typedef volatile uint32_t ioport32_t;
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/Makefile.toolchain
26,16 → 26,26
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
DEFS = -DARCH=$(ARCH)
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include -pipe
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration \
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \
-Wmissing-prototypes -O3 -nostdlib -nostdinc -imacros \
$(LIBC_PREFIX)/../../../config.h -I$(LIBC_PREFIX)/include -pipe -g
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
#-Werror
 
## Cross-toolchain prefix
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
## Setup platform configuration
#
 
include $(LIBC_PREFIX)/arch/$(ARCH)/Makefile.inc
-include $(LIBC_PREFIX)/../../../Makefile.config
-include $(LIBC_PREFIX)/../../../config.defs
-include $(LIBC_PREFIX)/arch/$(UARCH)/Makefile.inc
 
## Simple detection of the host system
#
59,6 → 69,7
AR = $(BINUTILS_PREFIX)ar
OBJCOPY = $(BINUTILS_PREFIX)objcopy
OBJDUMP = $(BINUTILS_PREFIX)objdump
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
ifeq ($(COMPILER),icc_native)
68,6 → 79,7
AR = ar
OBJCOPY = objcopy
OBJDUMP = objdump
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
ifeq ($(COMPILER),gcc_cross)
77,5 → 89,5
AR = $(TOOLCHAIN_DIR)/$(TARGET)-ar
OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
endif
 
/branches/tracing/uspace/lib/libc/generic/kbd.c
0,0 → 1,62
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <io/stream.h>
#include <kbd/kbd.h>
#include <ipc/ipc.h>
#include <ipc/console.h>
#include <console.h>
#include <async.h>
 
int kbd_get_event(kbd_event_t *ev)
{
int cons_phone = console_open(true);
ipcarg_t r0, r1, r2, r3;
int rc;
 
rc = async_req_0_4(cons_phone, CONSOLE_GETKEY, &r0, &r1, &r2, &r3);
if (rc < 0)
return -1;
 
ev->type = r0;
ev->key = r1;
ev->mods = r2;
ev->c = r3;
 
return 0;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/ddi.c
33,26 → 33,42
*/
 
#include <ddi.h>
#include <libarch/ddi.h>
#include <libc.h>
#include <task.h>
#include <as.h>
#include <align.h>
#include <libarch/config.h>
#include <kernel/ddi/ddi_arg.h>
 
/** Return unique device number.
*
* @return New unique device number.
*
*/
int device_assign_devno(void)
{
return __SYSCALL0(SYS_DEVICE_ASSIGN_DEVNO);
}
 
/** Map piece of physical memory to task.
*
* Caller of this function must have the CAP_MEM_MANAGER capability.
*
* @param pf Physical address of the starting frame.
* @param vp Virtual address of the sterting page.
* @param pages Number of pages to map.
* @param flags Flags for the new address space area.
* @param pf Physical address of the starting frame.
* @param vp Virtual address of the starting page.
* @param pages Number of pages to map.
* @param flags Flags for the new address space area.
*
* @return 0 on success, EPERM if the caller lacks the CAP_MEM_MANAGER capability,
* ENOENT if there is no task with specified ID and ENOMEM if there
* was some problem in creating address space area.
* @return 0 on success, EPERM if the caller lacks the
* CAP_MEM_MANAGER capability, ENOENT if there is no task
* with specified ID and ENOMEM if there was some problem
* in creating address space area.
*/
int physmem_map(void *pf, void *vp, unsigned long pages, int flags)
{
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, flags);
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages,
flags);
}
 
/** Enable I/O space range to task.
59,13 → 75,14
*
* Caller of this function must have the IO_MEM_MANAGER capability.
*
* @param id Task ID.
* @param ioaddr Starting address of the I/O range.
* @param size Size of the range.
* @param id Task ID.
* @param ioaddr Starting address of the I/O range.
* @param size Size of the range.
*
* @return 0 on success, EPERM if the caller lacks the CAP_IO_MANAGER capability,
* ENOENT if there is no task with specified ID and ENOMEM if there
* was some problem in allocating memory.
* @return 0 on success, EPERM if the caller lacks the
* CAP_IO_MANAGER capability, ENOENT if there is no task
* with specified ID and ENOMEM if there was some problem
* in allocating memory.
*/
int iospace_enable(task_id_t id, void *ioaddr, unsigned long size)
{
80,7 → 97,7
 
/** Interrupt control
*
* @param enable 1 - enable interrupts, 0 - disable interrupts
* @param enable 1 - enable interrupts, 0 - disable interrupts
*/
int preemption_control(int enable)
{
87,5 → 104,36
return __SYSCALL1(SYS_PREEMPT_CONTROL, (sysarg_t) enable);
}
 
/** Enable PIO for specified I/O range.
*
* @param pio_addr I/O start address.
* @param size Size of the I/O region.
* @param use_addr Address where the final address for application's PIO
* will be stored.
*
* @return Zero on success or negative error code.
*/
int pio_enable(void *pio_addr, size_t size, void **use_addr)
{
void *phys;
void *virt;
size_t offset;
unsigned int pages;
 
#ifdef IO_SPACE_BOUNDARY
if (pio_addr < IO_SPACE_BOUNDARY) {
*use_addr = pio_addr;
return iospace_enable(task_get_id(), pio_addr, size);
}
#endif
 
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
offset = pio_addr - phys;
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
virt = as_get_mappable_page(pages);
*use_addr = virt + offset;
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/console.c
0,0 → 1,274
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <libc.h>
#include <async.h>
#include <io/stream.h>
#include <ipc/console.h>
#include <ipc/services.h>
#include <errno.h>
#include <string.h>
#include <console.h>
 
static int console_phone = -1;
 
/** Size of cbuffer. */
#define CBUFFER_SIZE 256
 
/** Buffer for writing characters to the console. */
static char cbuffer[CBUFFER_SIZE];
 
/** Pointer to end of cbuffer. */
static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
 
/** Pointer to first available field in cbuffer. */
static char *cbp = cbuffer;
 
 
/** Write one character to the console via IPC. */
static void cons_putchar(wchar_t c)
{
console_wait();
async_msg_1(console_phone, CONSOLE_PUTCHAR, c);
}
 
/** Write characters to the console via IPC or to klog */
static ssize_t cons_write(const char *buf, size_t size)
{
console_open(false);
if (console_phone >= 0) {
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer);
ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return (ssize_t) rc;
}
async_wait_for(req, &rc);
async_serialize_end();
if (rc == EOK)
return (ssize_t) IPC_GET_ARG1(answer);
else
return -1;
} else
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
}
 
/** Write all data from output buffer to the console. */
static void cbuffer_flush(void)
{
size_t len = cbp - cbuffer;
while (len > 0) {
ssize_t rc = cons_write(cbuffer, cbp - cbuffer);
if (rc < 0)
return;
len -= rc;
}
cbp = cbuffer;
}
 
/** Drop all data in console output buffer. */
static void cbuffer_drain(void)
{
cbp = cbuffer;
}
 
/** Write one character to the output buffer. */
static inline void cbuffer_putc(char c)
{
if (cbp == cbuffer_end)
cbuffer_flush();
*cbp++ = c;
if (c == '\n')
cbuffer_flush();
}
 
int console_open(bool blocking)
{
if (console_phone < 0) {
int phone;
if (blocking)
phone = ipc_connect_me_to_blocking(PHONE_NS,
SERVICE_CONSOLE, 0, 0);
else
phone = ipc_connect_me_to(PHONE_NS,
SERVICE_CONSOLE, 0, 0);
if (phone >= 0)
console_phone = phone;
}
return console_phone;
}
 
void console_close(void)
{
if (console_phone >= 0) {
if (ipc_hangup(console_phone) == 0)
console_phone = -1;
}
}
 
void console_wait(void)
{
while (console_phone < 0)
console_open(true);
}
 
void console_clear(void)
{
console_wait();
cbuffer_drain();
async_msg_0(console_phone, CONSOLE_CLEAR);
}
 
int console_get_size(int *rows, int *cols)
{
console_wait();
ipcarg_t r;
ipcarg_t c;
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c);
*rows = (int) r;
*cols = (int) c;
return rc;
}
 
void console_set_style(int style)
{
console_wait();
cbuffer_flush();
async_msg_1(console_phone, CONSOLE_SET_STYLE, style);
}
 
void console_set_color(int fg_color, int bg_color, int flags)
{
console_wait();
cbuffer_flush();
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
}
 
void console_set_rgb_color(int fg_color, int bg_color)
{
console_wait();
cbuffer_flush();
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
}
 
void console_cursor_visibility(int show)
{
console_wait();
cbuffer_flush();
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
}
 
void console_kcon_enable(void)
{
console_wait();
cbuffer_flush();
async_msg_0(console_phone, CONSOLE_KCON_ENABLE);
}
 
void console_goto(int row, int col)
{
console_wait();
cbuffer_flush();
async_msg_2(console_phone, CONSOLE_GOTO, row, col);
}
 
void console_putchar(wchar_t c)
{
console_wait();
cbuffer_flush();
cons_putchar(c);
}
 
/** Write characters to the console. */
ssize_t console_write(const char *buf, size_t size)
{
size_t left = size;
while (left > 0) {
cbuffer_putc(*buf++);
left--;
}
return size;
}
 
/** Write a NULL-terminated string to the console. */
void console_putstr(const char *str)
{
size_t left = str_size(str);
while (left > 0) {
ssize_t rc = console_write(str, left);
if (rc < 0) {
/* Error */
return;
}
str += rc;
left -= rc;
}
}
 
/** Flush all output to the console or klog. */
void console_flush(void)
{
cbuffer_flush();
if (console_phone >= 0)
async_msg_0(console_phone, CONSOLE_FLUSH);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/task.c
38,6 → 38,7
#include <stdlib.h>
#include <errno.h>
#include <loader/loader.h>
#include <string.h>
 
task_id_t task_get_id(void)
{
48,6 → 49,17
return task_id;
}
 
/** Set the task name.
*
* @param name The new name, typically the command used to execute the
* program.
* @return Zero on success or negative error code.
*/
int task_set_name(const char *name)
{
return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, str_size(name));
}
 
/** Create a new task by running an executable from the filesystem.
*
* This is really just a convenience wrapper over the more complicated
63,8 → 75,8
task_id_t task_id;
int rc;
 
/* Spawn a program loader. */
ldr = loader_spawn(path);
/* Connect to a program loader. */
ldr = loader_connect();
if (ldr == NULL)
return 0;
 
89,7 → 101,6
goto error;
 
/* Run it. */
/* Load the program. */
rc = loader_run(ldr);
if (rc != EOK)
goto error;
/branches/tracing/uspace/lib/libc/generic/getopt.c
241,7 → 241,7
}
}
if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
(oli = str_chr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
/* option letter unknown or ':' */
if (!*place)
++optind;
377,20 → 377,20
nonopt_start = nonopt_end = -1;
return -1;
}
if ((has_equal = strchr(current_argv, '=')) != NULL) {
if ((has_equal = str_chr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
current_argv_len = str_size(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
if (str_lcmp(current_argv, long_options[i].name,
str_nlength(current_argv, current_argv_len)))
continue;
 
if (strlen(long_options[i].name) ==
if (str_size(long_options[i].name) ==
(unsigned)current_argv_len) {
/* exact match */
match = i;
/branches/tracing/uspace/lib/libc/generic/string.c
1,7 → 1,6
/*
* Copyright (c) 2005 Martin Decky
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com>
* Copyright (c) 1988, 1993 The Regents of the University of California.
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
35,180 → 34,665
*/
 
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <ctype.h>
#include <limits.h>
#include <malloc.h>
#include <errno.h>
#include <align.h>
#include <sys/types.h>
#include <malloc.h>
#include <mem.h>
#include <string.h>
 
/* Dummy implementation of mem/ functions */
/** Byte mask consisting of lowest @n bits (out of 8) */
#define LO_MASK_8(n) ((uint8_t) ((1 << (n)) - 1))
 
void *memset(void *s, int c, size_t n)
/** Byte mask consisting of lowest @n bits (out of 32) */
#define LO_MASK_32(n) ((uint32_t) ((1 << (n)) - 1))
 
/** Byte mask consisting of highest @n bits (out of 8) */
#define HI_MASK_8(n) (~LO_MASK_8(8 - (n)))
 
/** Number of data bits in a UTF-8 continuation byte */
#define CONT_BITS 6
 
/** Decode a single character from a string.
*
* Decode a single character from a string of size @a size. Decoding starts
* at @a offset and this offset is moved to the beginning of the next
* character. In case of decoding error, offset generally advances at least
* by one. However, offset is never moved beyond size.
*
* @param str String (not necessarily NULL-terminated).
* @param offset Byte offset in string where to start decoding.
* @param size Size of the string (in bytes).
*
* @return Value of decoded character, U_SPECIAL on decoding error or
* NULL if attempt to decode beyond @a size.
*
*/
wchar_t str_decode(const char *str, size_t *offset, size_t size)
{
char *os = s;
if (*offset + 1 > size)
return 0;
while (n--)
*(os++) = c;
/* First byte read from string */
uint8_t b0 = (uint8_t) str[(*offset)++];
return s;
/* Determine code length */
unsigned int b0_bits; /* Data bits in first byte */
unsigned int cbytes; /* Number of continuation bytes */
if ((b0 & 0x80) == 0) {
/* 0xxxxxxx (Plain ASCII) */
b0_bits = 7;
cbytes = 0;
} else if ((b0 & 0xe0) == 0xc0) {
/* 110xxxxx 10xxxxxx */
b0_bits = 5;
cbytes = 1;
} else if ((b0 & 0xf0) == 0xe0) {
/* 1110xxxx 10xxxxxx 10xxxxxx */
b0_bits = 4;
cbytes = 2;
} else if ((b0 & 0xf8) == 0xf0) {
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
b0_bits = 3;
cbytes = 3;
} else {
/* 10xxxxxx -- unexpected continuation byte */
return U_SPECIAL;
}
if (*offset + cbytes > size)
return U_SPECIAL;
wchar_t ch = b0 & LO_MASK_8(b0_bits);
/* Decode continuation bytes */
while (cbytes > 0) {
uint8_t b = (uint8_t) str[(*offset)++];
/* Must be 10xxxxxx */
if ((b & 0xc0) != 0x80)
return U_SPECIAL;
/* Shift data bits to ch */
ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
cbytes--;
}
return ch;
}
 
struct along {
unsigned long n;
} __attribute__ ((packed));
/** Encode a single character to string representation.
*
* Encode a single character to string representation (i.e. UTF-8) and store
* it into a buffer at @a offset. Encoding starts at @a offset and this offset
* is moved to the position where the next character can be written to.
*
* @param ch Input character.
* @param str Output buffer.
* @param offset Byte offset where to start writing.
* @param size Size of the output buffer (in bytes).
*
* @return EOK if the character was encoded successfully, EOVERFLOW if there
* was not enough space in the output buffer or EINVAL if the character
* code was invalid.
*/
int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
{
if (*offset >= size)
return EOVERFLOW;
if (!chr_check(ch))
return EINVAL;
/* Unsigned version of ch (bit operations should only be done
on unsigned types). */
uint32_t cc = (uint32_t) ch;
/* Determine how many continuation bytes are needed */
unsigned int b0_bits; /* Data bits in first byte */
unsigned int cbytes; /* Number of continuation bytes */
if ((cc & ~LO_MASK_32(7)) == 0) {
b0_bits = 7;
cbytes = 0;
} else if ((cc & ~LO_MASK_32(11)) == 0) {
b0_bits = 5;
cbytes = 1;
} else if ((cc & ~LO_MASK_32(16)) == 0) {
b0_bits = 4;
cbytes = 2;
} else if ((cc & ~LO_MASK_32(21)) == 0) {
b0_bits = 3;
cbytes = 3;
} else {
/* Codes longer than 21 bits are not supported */
return EINVAL;
}
/* Check for available space in buffer */
if (*offset + cbytes >= size)
return EOVERFLOW;
/* Encode continuation bytes */
unsigned int i;
for (i = cbytes; i > 0; i--) {
str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
cc = cc >> CONT_BITS;
}
/* Encode first byte */
str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
/* Advance offset */
*offset += cbytes + 1;
return EOK;
}
 
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
/** Get size of string.
*
* Get the number of bytes which are used by the string @a str (excluding the
* NULL-terminator).
*
* @param str String to consider.
*
* @return Number of bytes used by the string
*
*/
size_t str_size(const char *str)
{
int i, j;
struct along *adst = dst;
const struct along *asrc = src;
size_t size = 0;
while (*str++ != 0)
size++;
return size;
}
 
for (i = 0; i < n / sizeof(unsigned long); i++)
adst[i].n = asrc[i].n;
/** Get size of wide string.
*
* Get the number of bytes which are used by the wide string @a str (excluding the
* NULL-terminator).
*
* @param str Wide string to consider.
*
* @return Number of bytes used by the wide string
*
*/
size_t wstr_size(const wchar_t *str)
{
return (wstr_length(str) * sizeof(wchar_t));
}
 
/** Get size of string with length limit.
*
* Get the number of bytes which are used by up to @a max_len first
* characters in the string @a str. If @a max_len is greater than
* the length of @a str, the entire string is measured (excluding the
* NULL-terminator).
*
* @param str String to consider.
* @param max_len Maximum number of characters to measure.
*
* @return Number of bytes used by the characters.
*
*/
size_t str_lsize(const char *str, count_t max_len)
{
count_t len = 0;
size_t offset = 0;
while (len < max_len) {
if (str_decode(str, &offset, STR_NO_LIMIT) == 0)
break;
for (j = 0; j < n % sizeof(unsigned long); j++)
((unsigned char *) (((unsigned long *) dst) + i))[j] =
((unsigned char *) (((unsigned long *) src) + i))[j];
return (char *) dst;
len++;
}
return offset;
}
 
void *memcpy(void *dst, const void *src, size_t n)
/** Get size of wide string with length limit.
*
* Get the number of bytes which are used by up to @a max_len first
* wide characters in the wide string @a str. If @a max_len is greater than
* the length of @a str, the entire wide string is measured (excluding the
* NULL-terminator).
*
* @param str Wide string to consider.
* @param max_len Maximum number of wide characters to measure.
*
* @return Number of bytes used by the wide characters.
*
*/
size_t wstr_lsize(const wchar_t *str, count_t max_len)
{
int i, j;
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
}
 
if (((long) dst & (sizeof(long) - 1)) ||
((long) src & (sizeof(long) - 1)))
return unaligned_memcpy(dst, src, n);
/** Get number of characters in a string.
*
* @param str NULL-terminated string.
*
* @return Number of characters in string.
*
*/
count_t str_length(const char *str)
{
count_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
len++;
return len;
}
 
for (i = 0; i < n / sizeof(unsigned long); i++)
((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
for (j = 0; j < n % sizeof(unsigned long); j++)
((unsigned char *) (((unsigned long *) dst) + i))[j] =
((unsigned char *) (((unsigned long *) src) + i))[j];
return (char *) dst;
/** Get number of characters in a wide string.
*
* @param str NULL-terminated wide string.
*
* @return Number of characters in @a str.
*
*/
count_t wstr_length(const wchar_t *wstr)
{
count_t len = 0;
while (*wstr++ != 0)
len++;
return len;
}
 
void *memmove(void *dst, const void *src, size_t n)
/** Get number of characters in a string with size limit.
*
* @param str NULL-terminated string.
* @param size Maximum number of bytes to consider.
*
* @return Number of characters in string.
*
*/
count_t str_nlength(const char *str, size_t size)
{
int i, j;
count_t len = 0;
size_t offset = 0;
if (src > dst)
return memcpy(dst, src, n);
while (str_decode(str, &offset, size) != 0)
len++;
return len;
}
 
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
((unsigned char *) ((unsigned long *) dst))[j] =
((unsigned char *) ((unsigned long *) src))[j];
/** Get number of characters in a string with size limit.
*
* @param str NULL-terminated string.
* @param size Maximum number of bytes to consider.
*
* @return Number of characters in string.
*
*/
count_t wstr_nlength(const wchar_t *str, size_t size)
{
count_t len = 0;
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
count_t offset = 0;
while ((offset < limit) && (*str++ != 0)) {
len++;
offset += sizeof(wchar_t);
}
return len;
}
 
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
return (char *) dst;
/** Check whether character is plain ASCII.
*
* @return True if character is plain ASCII.
*
*/
bool ascii_check(wchar_t ch)
{
if ((ch >= 0) && (ch <= 127))
return true;
return false;
}
 
/** Compare two memory areas.
/** Check whether character is valid
*
* @param s1 Pointer to the first area to compare.
* @param s2 Pointer to the second area to compare.
* @param len Size of the first area in bytes. Both areas must have
* the same length.
* @return If len is 0, return zero. If the areas match, return
* zero. Otherwise return non-zero.
* @return True if character is a valid Unicode code point.
*
*/
int bcmp(const char *s1, const char *s2, size_t len)
bool chr_check(wchar_t ch)
{
for (; len && *s1++ == *s2++; len--)
;
return len;
if ((ch >= 0) && (ch <= 1114111))
return true;
return false;
}
 
/** Count the number of characters in the string, not including terminating 0.
/** Compare two NULL terminated strings.
*
* @param str String.
* @return Number of characters in string.
* Do a char-by-char comparison of two NULL-terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths.
*
* @param s1 First string to compare.
* @param s2 Second string to compare.
*
* @return 0 if the strings are equal, -1 if first is smaller,
* 1 if second smaller.
*
*/
size_t strlen(const char *str)
int str_cmp(const char *s1, const char *s2)
{
size_t counter = 0;
wchar_t c1 = 0;
wchar_t c2 = 0;
size_t off1 = 0;
size_t off2 = 0;
 
while (str[counter] != 0)
counter++;
while (true) {
c1 = str_decode(s1, &off1, STR_NO_LIMIT);
c2 = str_decode(s2, &off2, STR_NO_LIMIT);
 
return counter;
if (c1 < c2)
return -1;
if (c1 > c2)
return 1;
 
if (c1 == 0 || c2 == 0)
break;
}
 
return 0;
}
 
int strcmp(const char *a, const char *b)
/** Compare two NULL terminated strings with length limit.
*
* Do a char-by-char comparison of two NULL-terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths and the length limit.
*
* @param s1 First string to compare.
* @param s2 Second string to compare.
* @param max_len Maximum number of characters to consider.
*
* @return 0 if the strings are equal, -1 if first is smaller,
* 1 if second smaller.
*
*/
int str_lcmp(const char *s1, const char *s2, count_t max_len)
{
int c = 0;
wchar_t c1 = 0;
wchar_t c2 = 0;
while (a[c] && b[c] && (!(a[c] - b[c])))
c++;
size_t off1 = 0;
size_t off2 = 0;
return (a[c] - b[c]);
count_t len = 0;
 
while (true) {
if (len >= max_len)
break;
 
c1 = str_decode(s1, &off1, STR_NO_LIMIT);
c2 = str_decode(s2, &off2, STR_NO_LIMIT);
 
if (c1 < c2)
return -1;
 
if (c1 > c2)
return 1;
 
if (c1 == 0 || c2 == 0)
break;
 
++len;
}
 
return 0;
 
}
 
int strncmp(const char *a, const char *b, size_t n)
/** Copy string.
*
* Copy source string @a src to destination buffer @a dest.
* No more than @a size bytes are written. If the size of the output buffer
* is at least one byte, the output string will always be well-formed, i.e.
* null-terminated and containing only complete characters.
*
* @param dst Destination buffer.
* @param count Size of the destination buffer (must be > 0).
* @param src Source string.
*/
void str_cpy(char *dest, size_t size, const char *src)
{
size_t c = 0;
wchar_t ch;
size_t src_off;
size_t dest_off;
 
while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
c++;
/* There must be space for a null terminator in the buffer. */
assert(size > 0);
return ( c < n ? a[c] - b[c] : 0);
src_off = 0;
dest_off = 0;
 
while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
break;
}
 
dest[dest_off] = '\0';
}
 
/** Copy size-limited substring.
*
* Copy prefix of string @a src of max. size @a size to destination buffer
* @a dest. No more than @a size bytes are written. The output string will
* always be well-formed, i.e. null-terminated and containing only complete
* characters.
*
* No more than @a n bytes are read from the input string, so it does not
* have to be null-terminated.
*
* @param dst Destination buffer.
* @param count Size of the destination buffer (must be > 0).
* @param src Source string.
* @param n Maximum number of bytes to read from @a src.
*/
void str_ncpy(char *dest, size_t size, const char *src, size_t n)
{
wchar_t ch;
size_t src_off;
size_t dest_off;
 
/* There must be space for a null terminator in the buffer. */
assert(size > 0);
src_off = 0;
dest_off = 0;
 
while ((ch = str_decode(src, &src_off, n)) != 0) {
if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
break;
}
 
dest[dest_off] = '\0';
}
 
int stricmp(const char *a, const char *b)
/** Append one string to another.
*
* Append source string @a src to string in destination buffer @a dest.
* Size of the destination buffer is @a dest. If the size of the output buffer
* is at least one byte, the output string will always be well-formed, i.e.
* null-terminated and containing only complete characters.
*
* @param dst Destination buffer.
* @param count Size of the destination buffer.
* @param src Source string.
*/
void str_append(char *dest, size_t size, const char *src)
{
int c = 0;
size_t dstr_size;
 
dstr_size = str_size(dest);
str_cpy(dest + dstr_size, size - dstr_size, src);
}
 
/** Copy NULL-terminated wide string to string
*
* Copy source wide string @a src to destination buffer @a dst.
* No more than @a size bytes are written. NULL-terminator is always
* written after the last succesfully copied character (i.e. if the
* destination buffer is has at least 1 byte, it will be always
* NULL-terminated).
*
* @param src Source wide string.
* @param dst Destination buffer.
* @param count Size of the destination buffer.
*
*/
void wstr_nstr(char *dst, const wchar_t *src, size_t size)
{
/* No space for the NULL-terminator in the buffer */
if (size == 0)
return;
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
c++;
wchar_t ch;
count_t src_idx = 0;
size_t dst_off = 0;
return (tolower(a[c]) - tolower(b[c]));
while ((ch = src[src_idx++]) != 0) {
if (chr_encode(ch, dst, &dst_off, size) != EOK)
break;
}
if (dst_off >= size)
dst[size - 1] = 0;
else
dst[dst_off] = 0;
}
 
/** Return pointer to the first occurence of character c in string.
/** Find first occurence of character in string.
*
* @param str Scanned string.
* @param c Searched character (taken as one byte).
* @return Pointer to the matched character or NULL if it is not
* found in given string.
* @param str String to search.
* @param ch Character to look for.
*
* @return Pointer to character in @a str or NULL if not found.
*/
char *strchr(const char *str, int c)
const char *str_chr(const char *str, wchar_t ch)
{
while (*str != '\0') {
if (*str == (char) c)
return (char *) str;
str++;
wchar_t acc;
size_t off = 0;
size_t last = 0;
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
return (str + last);
last = off;
}
 
return NULL;
}
 
/** Return pointer to the last occurence of character c in string.
/** Find last occurence of character in string.
*
* @param str Scanned string.
* @param c Searched character (taken as one byte).
* @return Pointer to the matched character or NULL if it is not
* found in given string.
* @param str String to search.
* @param ch Character to look for.
*
* @return Pointer to character in @a str or NULL if not found.
*/
char *strrchr(const char *str, int c)
const char *str_rchr(const char *str, wchar_t ch)
{
char *retval = NULL;
 
while (*str != '\0') {
if (*str == (char) c)
retval = (char *) str;
str++;
wchar_t acc;
size_t off = 0;
size_t last = 0;
char *res = NULL;
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
res = (str + last);
last = off;
}
return res;
}
 
return (char *) retval;
/** Insert a wide character into a wide string.
*
* Insert a wide character into a wide string at position
* @a pos. The characters after the position are shifted.
*
* @param str String to insert to.
* @param ch Character to insert to.
* @param pos Character index where to insert.
@ @param max_pos Characters in the buffer.
*
* @return True if the insertion was sucessful, false if the position
* is out of bounds.
*
*/
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
{
count_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
count_t i;
for (i = len; i + 1 > pos; i--)
str[i + 1] = str[i];
str[pos] = ch;
return true;
}
 
/** Remove a wide character from a wide string.
*
* Remove a wide character from a wide string at position
* @a pos. The characters after the position are shifted.
*
* @param str String to remove from.
* @param pos Character index to remove.
*
* @return True if the removal was sucessful, false if the position
* is out of bounds.
*
*/
bool wstr_remove(wchar_t *str, count_t pos)
{
count_t len = wstr_length(str);
if (pos >= len)
return false;
count_t i;
for (i = pos + 1; i <= len; i++)
str[i - 1] = str[i];
return true;
}
 
int stricmp(const char *a, const char *b)
{
int c = 0;
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
c++;
return (tolower(a[c]) - tolower(b[c]));
}
 
/** Convert string to a number.
* Core of strtol and strtoul functions.
*
358,91 → 842,47
return (sgn ? -number : number);
}
 
char *strcpy(char *dest, const char *src)
char *str_dup(const char *src)
{
char *orig = dest;
while ((*(dest++) = *(src++)))
;
return orig;
}
size_t size = str_size(src);
void *dest = malloc(size + 1);
 
char *strncpy(char *dest, const char *src, size_t n)
{
char *orig = dest;
while ((*(dest++) = *(src++)) && --n)
;
return orig;
}
if (dest == NULL)
return (char *) NULL;
 
char *strcat(char *dest, const char *src)
{
char *orig = dest;
while (*dest++)
;
--dest;
while ((*dest++ = *src++))
;
return orig;
return (char *) memcpy(dest, src, size + 1);
}
 
char * strdup(const char *s1)
char *strtok(char *s, const char *delim)
{
size_t len = strlen(s1) + 1;
void *ret = malloc(len);
static char *next;
 
if (ret == NULL)
return (char *) NULL;
 
return (char *) memcpy(ret, s1, len);
return strtok_r(s, delim, &next);
}
 
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * strtok_r(char *s, const char *delim, char **last)
char *strtok_r(char *s, const char *delim, char **next)
{
char *spanp, *tok;
int c, sc;
char *start, *end;
 
if (s == NULL && (s = *last) == NULL)
return (NULL);
if (s == NULL)
s = *next;
 
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
/* Skip over leading delimiters. */
while (*s && (str_chr(delim, *s) != NULL)) ++s;
start = s;
 
if (c == 0) { /* no non-delimiter characters */
*last = NULL;
return (NULL);
}
/* Skip over token characters. */
while (*s && (str_chr(delim, *s) == NULL)) ++s;
end = s;
*next = (*s ? s + 1 : s);
 
tok = s - 1;
 
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = '\0';
*last = s;
return (tok);
}
} while (sc != 0);
if (start == end) {
return NULL; /* No more tokens. */
}
}
 
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * strtok(char *s, const char *delim)
{
static char *last;
 
return (strtok_r(s, delim, &last));
/* Overwrite delimiter with NULL terminator. */
*end = '\0';
return start;
}
 
/** @}
/branches/tracing/uspace/lib/libc/generic/loader.c
34,6 → 34,7
 
#include <ipc/ipc.h>
#include <ipc/loader.h>
#include <ipc/services.h>
#include <libc.h>
#include <task.h>
#include <string.h>
50,33 → 51,27
* @return Pointer to the loader connection structure (should be
* de-allocated using free() after use).
*/
loader_t *loader_spawn(char *name)
int loader_spawn(const char *name)
{
int phone_id, rc;
return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER,
(sysarg_t) name, str_size(name));
}
 
loader_t *loader_connect(void)
{
loader_t *ldr;
int phone_id;
 
/*
* Ask kernel to spawn a new loader task.
*/
rc = __SYSCALL3(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id,
(sysarg_t) name, strlen(name));
if (rc != 0)
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
if (phone_id < 0)
return NULL;
 
/*
* Say hello so that the loader knows the incoming connection's
* phone hash.
*/
rc = async_req_0_0(phone_id, LOADER_HELLO);
if (rc != EOK)
return NULL;
 
ldr = malloc(sizeof(loader_t));
if (ldr == NULL)
return NULL;
 
ldr->phone_id = phone_id;
return ldr;
return ldr;
}
 
/** Get ID of the new task.
173,7 → 168,7
ap = argv;
buffer_size = 0;
while (*ap != NULL) {
buffer_size += strlen(*ap) + 1;
buffer_size += str_size(*ap) + 1;
++ap;
}
 
183,9 → 178,10
/* Now fill the buffer with null-terminated argument strings */
ap = argv;
dp = arg_buf;
 
while (*ap != NULL) {
strcpy(dp, *ap);
dp += strlen(*ap) + 1;
str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
dp += str_size(*ap) + 1;
 
++ap;
}
247,6 → 243,8
if (rc != EOK)
return rc;
 
ipc_hangup(ldr->phone_id);
ldr->phone_id = 0;
return EOK;
}
 
/branches/tracing/uspace/lib/libc/generic/thread.c
109,7 → 109,7
uarg->uspace_uarg = uarg;
rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name,
(sysarg_t) strlen(name), (sysarg_t) tid);
(sysarg_t) str_size(name), (sysarg_t) tid);
if (rc) {
/*
130,6 → 130,8
void thread_exit(int status)
{
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
for (;;)
;
}
 
/** Detach thread.
152,6 → 154,7
*/
int thread_join(thread_id_t thread)
{
return 0;
}
 
/** Get current thread ID.
/branches/tracing/uspace/lib/libc/generic/libc.c
48,11 → 48,14
#include <ipc/ipc.h>
#include <async.h>
#include <as.h>
#include <console.h>
#include <loader/pcb.h>
 
extern char _heap;
extern int main(int argc, char *argv[]);
 
int _errno;
 
void _exit(int status)
{
thread_exit(status);
69,8 → 72,6
f = fibril_setup();
__tcb_set(f->tcb);
open_console();
 
/* Save the PCB pointer */
__pcb = (pcb_t *)pcb_ptr;
 
83,6 → 84,7
}
 
main(argc, argv);
console_flush();
}
 
void __exit(void)
/branches/tracing/uspace/lib/libc/generic/ipc.c
598,7 → 598,7
ipcarg_t newphid;
int res;
 
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
NULL, NULL, NULL, NULL, &newphid);
if (res)
return res;
605,6 → 605,30
return newphid;
}
 
/** Ask through phone for a new connection to some service.
*
* If the connection is not available at the moment, the
* call will block.
*
* @param phoneid Phone handle used for contacting the other side.
* @param arg1 User defined argument.
* @param arg2 User defined argument.
* @param arg3 User defined argument.
*
* @return New phone handle on success or a negative error code.
*/
int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3)
{
ipcarg_t newphid;
int res;
 
res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
if (res)
return res;
return newphid;
}
 
/** Hang up a phone.
*
* @param phoneid Handle of the phone to be hung up.
666,6 → 690,23
arg2, mode);
}
 
 
int ipc_forward_slow(ipc_callid_t callid, int phoneid, int method,
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5,
int mode)
{
ipc_call_t data;
 
IPC_SET_METHOD(data, method);
IPC_SET_ARG1(data, arg1);
IPC_SET_ARG2(data, arg2);
IPC_SET_ARG3(data, arg3);
IPC_SET_ARG4(data, arg4);
IPC_SET_ARG5(data, arg5);
 
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode);
}
 
/** Wrapper for making IPC_M_SHARE_IN calls.
*
* @param phoneid Phone that will be used to contact the receiving side.
/branches/tracing/uspace/lib/libc/generic/async.c
30,64 → 30,65
* @{
*/
/** @file
*/
*/
 
/**
* Asynchronous library
*
* The aim of this library is facilitating writing programs utilizing the
* asynchronous nature of HelenOS IPC, yet using a normal way of programming.
* The aim of this library is to provide a facility for writing programs which
* utilize the asynchronous nature of HelenOS IPC, yet using a normal way of
* programming.
*
* You should be able to write very simple multithreaded programs, the async
* framework will automatically take care of most synchronization problems.
*
* Default semantics:
* - async_send_*(): send asynchronously. If the kernel refuses to send
* more messages, [ try to get responses from kernel, if
* nothing found, might try synchronous ]
* - async_send_*(): Send asynchronously. If the kernel refuses to send
* more messages, [ try to get responses from kernel, if
* nothing found, might try synchronous ]
*
* Example of use (pseudo C):
*
*
* 1) Multithreaded client application
*
* fibril_create(fibril1, ...);
* fibril_create(fibril2, ...);
* ...
*
* int fibril1(void *arg)
* {
* conn = ipc_connect_me_to();
* c1 = async_send(conn);
* c2 = async_send(conn);
* async_wait_for(c1);
* async_wait_for(c2);
* ...
* }
* fibril_create(fibril1, ...);
* fibril_create(fibril2, ...);
* ...
*
* int fibril1(void *arg)
* {
* conn = ipc_connect_me_to();
* c1 = async_send(conn);
* c2 = async_send(conn);
* async_wait_for(c1);
* async_wait_for(c2);
* ...
* }
*
*
* 2) Multithreaded server application
* main()
* {
* async_manager();
* }
*
*
* my_client_connection(icallid, *icall)
* {
* if (want_refuse) {
* ipc_answer_0(icallid, ELIMIT);
* return;
* }
* ipc_answer_0(icallid, EOK);
* main()
* {
* async_manager();
* }
*
* callid = async_get_call(&call);
* handle_call(callid, call);
* ipc_answer_2(callid, 1, 2, 3);
* my_client_connection(icallid, *icall)
* {
* if (want_refuse) {
* ipc_answer_0(icallid, ELIMIT);
* return;
* }
* ipc_answer_0(icallid, EOK);
*
* callid = async_get_call(&call);
* ....
* }
* callid = async_get_call(&call);
* handle_call(callid, call);
* ipc_answer_2(callid, 1, 2, 3);
*
* callid = async_get_call(&call);
* ...
* }
*
*/
 
#include <futex.h>
104,24 → 105,26
#include <bool.h>
 
atomic_t async_futex = FUTEX_INITIALIZER;
static hash_table_t conn_hash_table;
static LIST_INITIALIZE(timeout_list);
 
/** Structures of this type represent a waiting fibril. */
typedef struct {
/** Expiration time. */
struct timeval expires;
struct timeval expires;
/** If true, this struct is in the timeout list. */
int inlist;
bool inlist;
/** Timeout list link. */
link_t link;
 
/** Identification of and link to the waiting fibril. */
fid_t fid;
/** If true, this fibril is currently active. */
int active;
bool active;
/** If true, we have timed out. */
int timedout;
bool timedout;
} awaiter_t;
 
typedef struct {
128,10 → 131,11
awaiter_t wdata;
/** If reply was received. */
int done;
bool done;
/** Pointer to where the answer data is stored. */
ipc_call_t *dataptr;
 
ipc_call_t *dataptr;
ipcarg_t retval;
} amsg_t;
 
147,24 → 151,24
 
typedef struct {
awaiter_t wdata;
 
/** Hash table link. */
link_t link;
 
/** Incoming phone hash. */
ipcarg_t in_phone_hash;
 
ipcarg_t in_phone_hash;
/** Messages that should be delivered to this fibril. */
link_t msg_queue;
link_t msg_queue;
/** Identification of the opening call. */
ipc_callid_t callid;
/** Call data of the opening call. */
ipc_call_t call;
 
/** Identification of the closing call. */
ipc_callid_t close_callid;
 
/** Fibril function that will be used to handle the connection. */
void (*cfibril)(ipc_callid_t, ipc_call_t *);
} connection_t;
172,12 → 176,6
/** Identifier of the incoming connection handled by the current fibril. */
__thread connection_t *FIBRIL_connection;
 
/**
* If true, it is forbidden to use async_req functions and all preemption is
* disabled.
*/
__thread int _in_interrupt_handler;
 
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
 
185,6 → 183,7
* Pointer to a fibril function that will be used to handle connections.
*/
static async_client_conn_t client_connection = default_client_connection;
 
/**
* Pointer to a fibril function that will be used to handle interrupt
* notifications.
191,46 → 190,39
*/
static async_client_conn_t interrupt_received = default_interrupt_received;
 
/*
* Getter for _in_interrupt_handler. We need to export the value of this thread
* local variable to other modules, but the binutils 2.18 linkers die on an
* attempt to export this symbol in the header file. For now, consider this as a
* workaround.
*/
bool in_interrupt_handler(void)
{
return _in_interrupt_handler;
}
 
#define CONN_HASH_TABLE_CHAINS 32
static hash_table_t conn_hash_table;
static LIST_INITIALIZE(timeout_list);
 
 
#define CONN_HASH_TABLE_CHAINS 32
 
/** Compute hash into the connection hash table based on the source phone hash.
*
* @param key Pointer to source phone hash.
* @param key Pointer to source phone hash.
*
* @return Index into the connection hash table.
* @return Index into the connection hash table.
*
*/
static hash_index_t conn_hash(unsigned long *key)
{
assert(key);
return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS;
return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS);
}
 
/** Compare hash table item with a key.
*
* @param key Array containing the source phone hash as the only item.
* @param keys Expected 1 but ignored.
* @param item Connection hash table item.
* @param key Array containing the source phone hash as the only item.
* @param keys Expected 1 but ignored.
* @param item Connection hash table item.
*
* @return True on match, false otherwise.
* @return True on match, false otherwise.
*
*/
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
connection_t *hs;
 
hs = hash_table_get_instance(item, connection_t, link);
return key[0] == hs->in_phone_hash;
connection_t *hs = hash_table_get_instance(item, connection_t, link);
return (key[0] == hs->in_phone_hash);
}
 
/** Connection hash table removal callback function.
238,7 → 230,8
* This function is called whenever a connection is removed from the connection
* hash table.
*
* @param item Connection hash table item being removed.
* @param item Connection hash table item being removed.
*
*/
static void conn_remove(link_t *item)
{
255,23 → 248,24
 
/** Sort in current fibril's timeout request.
*
* @param wd Wait data of the current fibril.
* @param wd Wait data of the current fibril.
*
*/
static void insert_timeout(awaiter_t *wd)
{
link_t *tmp;
awaiter_t *cur;
 
wd->timedout = 0;
wd->inlist = 1;
 
tmp = timeout_list.next;
wd->timedout = false;
wd->inlist = true;
link_t *tmp = timeout_list.next;
while (tmp != &timeout_list) {
cur = list_get_instance(tmp, awaiter_t, link);
awaiter_t *cur = list_get_instance(tmp, awaiter_t, link);
if (tv_gteq(&cur->expires, &wd->expires))
break;
tmp = tmp->next;
}
list_append(&wd->link, tmp);
}
 
281,93 → 275,146
* its message queue. If the fibril was not active, it is activated and all
* timeouts are unregistered.
*
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
*
* @return Zero if the call doesn't match any connection.
* One if the call was passed to the respective connection
* fibril.
* @return False if the call doesn't match any connection.
* True if the call was passed to the respective connection fibril.
*
*/
static int route_call(ipc_callid_t callid, ipc_call_t *call)
static bool route_call(ipc_callid_t callid, ipc_call_t *call)
{
connection_t *conn;
msg_t *msg;
link_t *hlp;
unsigned long key;
 
futex_down(&async_futex);
 
key = call->in_phone_hash;
hlp = hash_table_find(&conn_hash_table, &key);
unsigned long key = call->in_phone_hash;
link_t *hlp = hash_table_find(&conn_hash_table, &key);
if (!hlp) {
futex_up(&async_futex);
return 0;
return false;
}
conn = hash_table_get_instance(hlp, connection_t, link);
 
msg = malloc(sizeof(*msg));
connection_t *conn = hash_table_get_instance(hlp, connection_t, link);
msg_t *msg = malloc(sizeof(*msg));
if (!msg) {
futex_up(&async_futex);
return false;
}
msg->callid = callid;
msg->call = *call;
list_append(&msg->link, &conn->msg_queue);
 
if (IPC_GET_METHOD(*call) == IPC_M_PHONE_HUNGUP)
conn->close_callid = callid;
/* If the connection fibril is waiting for an event, activate it */
if (!conn->wdata.active) {
/* If in timeout list, remove it */
if (conn->wdata.inlist) {
conn->wdata.inlist = 0;
conn->wdata.inlist = false;
list_remove(&conn->wdata.link);
}
conn->wdata.active = 1;
conn->wdata.active = true;
fibril_add_ready(conn->wdata.fid);
}
 
futex_up(&async_futex);
return true;
}
 
return 1;
/** Notification fibril.
*
* When a notification arrives, a fibril with this implementing function is
* created. It calls interrupt_received() and does the final cleanup.
*
* @param arg Message structure pointer.
*
* @return Always zero.
*
*/
static int notification_fibril(void *arg)
{
msg_t *msg = (msg_t *) arg;
interrupt_received(msg->callid, &msg->call);
free(msg);
return 0;
}
 
/** Process interrupt notification.
*
* A new fibril is created which would process the notification.
*
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
*
* @return False if an error occured.
* True if the call was passed to the notification fibril.
*
*/
static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
{
futex_down(&async_futex);
msg_t *msg = malloc(sizeof(*msg));
if (!msg) {
futex_up(&async_futex);
return false;
}
msg->callid = callid;
msg->call = *call;
fid_t fid = fibril_create(notification_fibril, msg);
fibril_add_ready(fid);
futex_up(&async_futex);
return true;
}
 
/** Return new incoming message for the current (fibril-local) connection.
*
* @param call Storage where the incoming call data will be stored.
* @param usecs Timeout in microseconds. Zero denotes no timeout.
* @param call Storage where the incoming call data will be stored.
* @param usecs Timeout in microseconds. Zero denotes no timeout.
*
* @return If no timeout was specified, then a hash of the
* incoming call is returned. If a timeout is specified,
* then a hash of the incoming call is returned unless
* the timeout expires prior to receiving a message. In
* that case zero is returned.
* @return If no timeout was specified, then a hash of the
* incoming call is returned. If a timeout is specified,
* then a hash of the incoming call is returned unless
* the timeout expires prior to receiving a message. In
* that case zero is returned.
*
*/
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
{
msg_t *msg;
ipc_callid_t callid;
connection_t *conn;
assert(FIBRIL_connection);
assert(FIBRIL_connection);
/* GCC 4.1.0 coughs on FIBRIL_connection-> dereference,
/* Why doing this?
* GCC 4.1.0 coughs on FIBRIL_connection-> dereference.
* GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
* I would never expect to find so many errors in
* a compiler *($&$(*&$
* I would never expect to find so many errors in
* a compiler.
*/
conn = FIBRIL_connection;
 
connection_t *conn = FIBRIL_connection;
futex_down(&async_futex);
 
if (usecs) {
gettimeofday(&conn->wdata.expires, NULL);
tv_add(&conn->wdata.expires, usecs);
} else {
conn->wdata.inlist = 0;
}
} else
conn->wdata.inlist = false;
/* If nothing in queue, wait until something arrives */
while (list_empty(&conn->msg_queue)) {
if (usecs)
insert_timeout(&conn->wdata);
 
conn->wdata.active = 0;
conn->wdata.active = false;
/*
* Note: the current fibril will be rescheduled either due to a
* timeout or due to an arriving message destined to it. In the
375,13 → 422,14
* case, route_call() will perform the wakeup.
*/
fibril_switch(FIBRIL_TO_MANAGER);
/*
* Futex is up after getting back from async_manager get it
* again.
* Futex is up after getting back from async_manager.
* Get it again.
*/
futex_down(&async_futex);
if (usecs && conn->wdata.timedout &&
list_empty(&conn->msg_queue)) {
if ((usecs) && (conn->wdata.timedout)
&& (list_empty(&conn->msg_queue))) {
/* If we timed out -> exit */
futex_up(&async_futex);
return 0;
388,9 → 436,10
}
}
msg = list_get_instance(conn->msg_queue.next, msg_t, link);
msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link);
list_remove(&msg->link);
callid = msg->callid;
ipc_callid_t callid = msg->callid;
*call = msg->call;
free(msg);
402,8 → 451,9
*
* This function is defined as a weak symbol - to be redefined in user code.
*
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
*
*/
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
{
412,8 → 462,11
 
/** Default fibril function that gets called to handle interrupt notifications.
*
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
* This function is defined as a weak symbol - to be redefined in user code.
*
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
*
*/
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
{
424,17 → 477,17
* When a new connection arrives, a fibril with this implementing function is
* created. It calls client_connection() and does the final cleanup.
*
* @param arg Connection structure pointer.
* @param arg Connection structure pointer.
*
* @return Always zero.
* @return Always zero.
*
*/
static int connection_fibril(void *arg)
static int connection_fibril(void *arg)
{
unsigned long key;
msg_t *msg;
int close_answered = 0;
 
/* Setup fibril-local connection pointer */
/*
* Setup fibril-local connection pointer and call client_connection().
*
*/
FIBRIL_connection = (connection_t *) arg;
FIBRIL_connection->cfibril(FIBRIL_connection->callid,
&FIBRIL_connection->call);
441,20 → 494,20
/* Remove myself from the connection hash table */
futex_down(&async_futex);
key = FIBRIL_connection->in_phone_hash;
unsigned long key = FIBRIL_connection->in_phone_hash;
hash_table_remove(&conn_hash_table, &key, 1);
futex_up(&async_futex);
/* Answer all remaining messages with EHANGUP */
while (!list_empty(&FIBRIL_connection->msg_queue)) {
msg = list_get_instance(FIBRIL_connection->msg_queue.next,
msg_t, link);
msg_t *msg
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link);
list_remove(&msg->link);
if (msg->callid == FIBRIL_connection->close_callid)
close_answered = 1;
ipc_answer_0(msg->callid, EHANGUP);
free(msg);
}
if (FIBRIL_connection->close_callid)
ipc_answer_0(FIBRIL_connection->close_callid, EOK);
463,43 → 516,45
 
/** Create a new fibril for a new connection.
*
* Creates new fibril for connection, fills in connection structures and inserts
* Create new fibril for connection, fill in connection structures and inserts
* it into the hash table, so that later we can easily do routing of messages to
* particular fibrils.
*
* @param in_phone_hash Identification of the incoming connection.
* @param callid Hash of the opening IPC_M_CONNECT_ME_TO call.
* If callid is zero, the connection was opened by
* accepting the IPC_M_CONNECT_TO_ME call and this function
* is called directly by the server.
* @param call Call data of the opening call.
* @param cfibril Fibril function that should be called upon opening the
* connection.
* @param in_phone_hash Identification of the incoming connection.
* @param callid Hash of the opening IPC_M_CONNECT_ME_TO call.
* If callid is zero, the connection was opened by
* accepting the IPC_M_CONNECT_TO_ME call and this function
* is called directly by the server.
* @param call Call data of the opening call.
* @param cfibril Fibril function that should be called upon opening the
* connection.
*
* @return New fibril id or NULL on failure.
* @return New fibril id or NULL on failure.
*
*/
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *))
{
connection_t *conn;
unsigned long key;
 
conn = malloc(sizeof(*conn));
connection_t *conn = malloc(sizeof(*conn));
if (!conn) {
if (callid)
ipc_answer_0(callid, ENOMEM);
return NULL;
}
conn->in_phone_hash = in_phone_hash;
list_initialize(&conn->msg_queue);
conn->callid = callid;
conn->close_callid = 0;
conn->close_callid = false;
if (call)
conn->call = *call;
conn->wdata.active = 1; /* We will activate the fibril ASAP */
/* We will activate the fibril ASAP */
conn->wdata.active = true;
conn->cfibril = cfibril;
 
conn->wdata.fid = fibril_create(connection_fibril, conn);
if (!conn->wdata.fid) {
free(conn);
if (callid)
506,14 → 561,16
ipc_answer_0(callid, ENOMEM);
return NULL;
}
/* Add connection to the connection hash table */
key = conn->in_phone_hash;
ipcarg_t key = conn->in_phone_hash;
futex_down(&async_futex);
hash_table_insert(&conn_hash_table, &key, &conn->link);
futex_up(&async_futex);
 
fibril_add_ready(conn->wdata.fid);
 
return conn->wdata.fid;
}
 
522,19 → 579,18
* If the call has the IPC_M_CONNECT_ME_TO method, a new connection is created.
* Otherwise the call is routed to its connection fibril.
*
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
* @param callid Hash of the incoming call.
* @param call Data of the incoming call.
*
*/
static void handle_call(ipc_callid_t callid, ipc_call_t *call)
{
/* Unrouted call - do some default behaviour */
if ((callid & IPC_CALLID_NOTIFICATION)) {
_in_interrupt_handler = 1;
(*interrupt_received)(callid, call);
_in_interrupt_handler = 0;
process_notification(callid, call);
return;
}
 
}
switch (IPC_GET_METHOD(*call)) {
case IPC_M_CONNECT_ME_TO:
/* Open new connection with fibril etc. */
542,11 → 598,11
client_connection);
return;
}
 
/* Try to route the call through the connection hash table */
if (route_call(callid, call))
return;
 
/* Unknown call from unknown phone - hang it up */
ipc_answer_0(callid, EHANGUP);
}
555,47 → 611,44
static void handle_expired_timeouts(void)
{
struct timeval tv;
awaiter_t *waiter;
link_t *cur;
 
gettimeofday(&tv, NULL);
futex_down(&async_futex);
 
cur = timeout_list.next;
link_t *cur = timeout_list.next;
while (cur != &timeout_list) {
waiter = list_get_instance(cur, awaiter_t, link);
awaiter_t *waiter = list_get_instance(cur, awaiter_t, link);
if (tv_gt(&waiter->expires, &tv))
break;
cur = cur->next;
list_remove(&waiter->link);
waiter->inlist = 0;
waiter->timedout = 1;
waiter->inlist = false;
waiter->timedout = true;
/*
* Redundant condition?
* The fibril should not be active when it gets here.
* Redundant condition?
* The fibril should not be active when it gets here.
*/
if (!waiter->active) {
waiter->active = 1;
waiter->active = true;
fibril_add_ready(waiter->fid);
}
}
 
futex_up(&async_futex);
}
 
/** Endless loop dispatching incoming calls and answers.
*
* @return Never returns.
* @return Never returns.
*
*/
static int async_manager_worker(void)
{
ipc_call_t call;
ipc_callid_t callid;
int timeout;
awaiter_t *waiter;
struct timeval tv;
 
while (1) {
while (true) {
if (fibril_switch(FIBRIL_FROM_MANAGER)) {
futex_up(&async_futex);
/*
604,11 → 657,17
*/
continue;
}
futex_down(&async_futex);
suseconds_t timeout;
if (!list_empty(&timeout_list)) {
waiter = list_get_instance(timeout_list.next, awaiter_t,
link);
awaiter_t *waiter
= list_get_instance(timeout_list.next, awaiter_t, link);
struct timeval tv;
gettimeofday(&tv, NULL);
if (tv_gteq(&tv, &waiter->expires)) {
futex_up(&async_futex);
handle_expired_timeouts();
617,19 → 676,21
timeout = tv_sub(&waiter->expires, &tv);
} else
timeout = SYNCH_NO_TIMEOUT;
futex_up(&async_futex);
 
callid = ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE);
 
ipc_call_t call;
ipc_callid_t callid
= ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE);
if (!callid) {
handle_expired_timeouts();
continue;
}
 
if (callid & IPC_CALLID_ANSWERED) {
if (callid & IPC_CALLID_ANSWERED)
continue;
}
 
handle_call(callid, &call);
}
637,16 → 698,17
}
 
/** Function to start async_manager as a standalone fibril.
*
*
* When more kernel threads are used, one async manager should exist per thread.
*
* @param arg Unused.
* @param arg Unused.
* @return Never returns.
*
* @return Never returns.
*/
static int async_manager_fibril(void *arg)
{
futex_up(&async_futex);
/*
* async_futex is always locked when entering manager
*/
658,9 → 720,7
/** Add one manager to manager list. */
void async_create_manager(void)
{
fid_t fid;
 
fid = fibril_create(async_manager_fibril, NULL);
fid_t fid = fibril_create(async_manager_fibril, NULL);
fibril_add_manager(fid);
}
 
672,7 → 732,7
 
/** Initialize the async framework.
*
* @return Zero on success or an error code.
* @return Zero on success or an error code.
*/
int _async_init(void)
{
692,30 → 752,33
*
* Notify the fibril which is waiting for this message that it has arrived.
*
* @param private Pointer to the asynchronous message record.
* @param retval Value returned in the answer.
* @param data Call data of the answer.
* @param arg Pointer to the asynchronous message record.
* @param retval Value returned in the answer.
* @param data Call data of the answer.
*/
static void reply_received(void *private, int retval, ipc_call_t *data)
static void reply_received(void *arg, int retval, ipc_call_t *data)
{
amsg_t *msg = (amsg_t *) private;
 
amsg_t *msg = (amsg_t *) arg;
msg->retval = retval;
 
futex_down(&async_futex);
/* Copy data after futex_down, just in case the call was detached */
if (msg->dataptr)
*msg->dataptr = *data;
 
*msg->dataptr = *data;
write_barrier();
/* Remove message from timeout list */
if (msg->wdata.inlist)
list_remove(&msg->wdata.link);
msg->done = 1;
msg->done = true;
if (!msg->wdata.active) {
msg->wdata.active = 1;
msg->wdata.active = true;
fibril_add_ready(msg->wdata.fid);
}
futex_up(&async_futex);
}
 
724,38 → 787,35
* The return value can be used as input for async_wait() to wait for
* completion.
*
* @param phoneid Handle of the phone that will be used for the send.
* @param method Service-defined method.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param dataptr If non-NULL, storage where the reply data will be
* stored.
* @param phoneid Handle of the phone that will be used for the send.
* @param method Service-defined method.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param dataptr If non-NULL, storage where the reply data will be
* stored.
*
* @return Hash of the sent message.
* @return Hash of the sent message or 0 on error.
*
*/
aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr)
{
amsg_t *msg;
 
if (_in_interrupt_handler) {
printf("Cannot send asynchronous request in interrupt "
"handler.\n");
_exit(1);
}
 
msg = malloc(sizeof(*msg));
msg->done = 0;
amsg_t *msg = malloc(sizeof(*msg));
if (!msg)
return 0;
msg->done = false;
msg->dataptr = dataptr;
 
/* We may sleep in the next method, but it will use its own mechanism */
msg->wdata.active = 1;
msg->wdata.active = true;
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
reply_received, 1);
 
reply_received, true);
return (aid_t) msg;
}
 
764,113 → 824,118
* The return value can be used as input for async_wait() to wait for
* completion.
*
* @param phoneid Handle of the phone that will be used for the send.
* @param method Service-defined method.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param arg5 Service-defined payload argument.
* @param dataptr If non-NULL, storage where the reply data will be
* stored.
* @param phoneid Handle of the phone that will be used for the send.
* @param method Service-defined method.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param arg5 Service-defined payload argument.
* @param dataptr If non-NULL, storage where the reply data will be
* stored.
*
* @return Hash of the sent message.
* @return Hash of the sent message or 0 on error.
*
*/
aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5,
ipc_call_t *dataptr)
{
amsg_t *msg;
 
if (_in_interrupt_handler) {
printf("Cannot send asynchronous request in interrupt "
"handler.\n");
_exit(1);
}
 
msg = malloc(sizeof(*msg));
msg->done = 0;
amsg_t *msg = malloc(sizeof(*msg));
if (!msg)
return 0;
msg->done = false;
msg->dataptr = dataptr;
 
/* We may sleep in next method, but it will use its own mechanism */
msg->wdata.active = 1;
 
msg->wdata.active = true;
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
reply_received, 1);
 
reply_received, true);
return (aid_t) msg;
}
 
/** Wait for a message sent by the async framework.
*
* @param amsgid Hash of the message to wait for.
* @param retval Pointer to storage where the retval of the answer will
* be stored.
* @param amsgid Hash of the message to wait for.
* @param retval Pointer to storage where the retval of the answer will
* be stored.
*
*/
void async_wait_for(aid_t amsgid, ipcarg_t *retval)
{
amsg_t *msg = (amsg_t *) amsgid;
 
futex_down(&async_futex);
if (msg->done) {
futex_up(&async_futex);
goto done;
}
 
msg->wdata.fid = fibril_get_id();
msg->wdata.active = 0;
msg->wdata.inlist = 0;
msg->wdata.active = false;
msg->wdata.inlist = false;
/* Leave the async_futex locked when entering this function */
fibril_switch(FIBRIL_TO_MANAGER);
/* futex is up automatically after fibril_switch...*/
/* Futex is up automatically after fibril_switch */
done:
if (retval)
*retval = msg->retval;
free(msg);
}
 
/** Wait for a message sent by the async framework, timeout variant.
*
* @param amsgid Hash of the message to wait for.
* @param retval Pointer to storage where the retval of the answer will
* be stored.
* @param timeout Timeout in microseconds.
* @param amsgid Hash of the message to wait for.
* @param retval Pointer to storage where the retval of the answer will
* be stored.
* @param timeout Timeout in microseconds.
*
* @return Zero on success, ETIMEOUT if the timeout has expired.
* @return Zero on success, ETIMEOUT if the timeout has expired.
*
*/
int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, suseconds_t timeout)
{
amsg_t *msg = (amsg_t *) amsgid;
 
/* TODO: Let it go through the event read at least once */
if (timeout < 0)
return ETIMEOUT;
 
futex_down(&async_futex);
if (msg->done) {
futex_up(&async_futex);
goto done;
}
 
gettimeofday(&msg->wdata.expires, NULL);
tv_add(&msg->wdata.expires, timeout);
 
msg->wdata.fid = fibril_get_id();
msg->wdata.active = 0;
msg->wdata.active = false;
insert_timeout(&msg->wdata);
 
/* Leave the async_futex locked when entering this function */
fibril_switch(FIBRIL_TO_MANAGER);
/* futex is up automatically after fibril_switch...*/
 
/* Futex is up automatically after fibril_switch */
if (!msg->done)
return ETIMEOUT;
 
done:
if (retval)
*retval = msg->retval;
free(msg);
 
return 0;
}
 
878,38 → 943,38
*
* The current fibril is suspended but the thread continues to execute.
*
* @param timeout Duration of the wait in microseconds.
* @param timeout Duration of the wait in microseconds.
*
*/
void async_usleep(suseconds_t timeout)
{
amsg_t *msg;
amsg_t *msg = malloc(sizeof(*msg));
if (_in_interrupt_handler) {
printf("Cannot call async_usleep in interrupt handler.\n");
_exit(1);
}
 
msg = malloc(sizeof(*msg));
if (!msg)
return;
 
msg->wdata.fid = fibril_get_id();
msg->wdata.active = 0;
 
msg->wdata.active = false;
gettimeofday(&msg->wdata.expires, NULL);
tv_add(&msg->wdata.expires, timeout);
 
futex_down(&async_futex);
insert_timeout(&msg->wdata);
/* Leave the async_futex locked when entering this function */
fibril_switch(FIBRIL_TO_MANAGER);
/* futex is up automatically after fibril_switch()...*/
/* Futex is up automatically after fibril_switch() */
free(msg);
}
 
/** Setter for client_connection function pointer.
*
* @param conn Function that will implement a new connection fibril.
* @param conn Function that will implement a new connection fibril.
*
*/
void async_set_client_connection(async_client_conn_t conn)
{
918,12 → 983,12
 
/** Setter for interrupt_received function pointer.
*
* @param conn Function that will implement a new interrupt
* notification fibril.
* @param intr Function that will implement a new interrupt
* notification fibril.
*/
void async_set_interrupt_received(async_client_conn_t conn)
void async_set_interrupt_received(async_client_conn_t intr)
{
interrupt_received = conn;
interrupt_received = intr;
}
 
/** Pseudo-synchronous message sending - fast version.
933,18 → 998,20
* This function can only transfer 4 register payload arguments. For
* transferring more arguments, see the slower async_req_slow().
*
* @param phoneid Hash of the phone through which to make the call.
* @param method Method of the call.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param r1 If non-NULL, storage for the 1st reply argument.
* @param r2 If non-NULL, storage for the 2nd reply argument.
* @param r3 If non-NULL, storage for the 3rd reply argument.
* @param r4 If non-NULL, storage for the 4th reply argument.
* @param r5 If non-NULL, storage for the 5th reply argument.
* @return Return code of the reply or a negative error code.
* @param phoneid Hash of the phone through which to make the call.
* @param method Method of the call.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param r1 If non-NULL, storage for the 1st reply argument.
* @param r2 If non-NULL, storage for the 2nd reply argument.
* @param r3 If non-NULL, storage for the 3rd reply argument.
* @param r4 If non-NULL, storage for the 4th reply argument.
* @param r5 If non-NULL, storage for the 5th reply argument.
*
* @return Return code of the reply or a negative error code.
*
*/
ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2,
951,21 → 1018,27
ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5)
{
ipc_call_t result;
ipcarg_t rc;
 
aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
&result);
ipcarg_t rc;
async_wait_for(eid, &rc);
if (r1)
if (r1)
*r1 = IPC_GET_ARG1(result);
if (r2)
*r2 = IPC_GET_ARG2(result);
if (r3)
*r3 = IPC_GET_ARG3(result);
if (r4)
*r4 = IPC_GET_ARG4(result);
if (r5)
*r5 = IPC_GET_ARG5(result);
return rc;
}
 
973,19 → 1046,21
*
* Send message asynchronously and return only after the reply arrives.
*
* @param phoneid Hash of the phone through which to make the call.
* @param method Method of the call.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param arg5 Service-defined payload argument.
* @param r1 If non-NULL, storage for the 1st reply argument.
* @param r2 If non-NULL, storage for the 2nd reply argument.
* @param r3 If non-NULL, storage for the 3rd reply argument.
* @param r4 If non-NULL, storage for the 4th reply argument.
* @param r5 If non-NULL, storage for the 5th reply argument.
* @return Return code of the reply or a negative error code.
* @param phoneid Hash of the phone through which to make the call.
* @param method Method of the call.
* @param arg1 Service-defined payload argument.
* @param arg2 Service-defined payload argument.
* @param arg3 Service-defined payload argument.
* @param arg4 Service-defined payload argument.
* @param arg5 Service-defined payload argument.
* @param r1 If non-NULL, storage for the 1st reply argument.
* @param r2 If non-NULL, storage for the 2nd reply argument.
* @param r3 If non-NULL, storage for the 3rd reply argument.
* @param r4 If non-NULL, storage for the 4th reply argument.
* @param r5 If non-NULL, storage for the 5th reply argument.
*
* @return Return code of the reply or a negative error code.
*
*/
ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1,
992,21 → 1067,27
ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5)
{
ipc_call_t result;
ipcarg_t rc;
 
aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
&result);
ipcarg_t rc;
async_wait_for(eid, &rc);
if (r1)
if (r1)
*r1 = IPC_GET_ARG1(result);
if (r2)
*r2 = IPC_GET_ARG2(result);
if (r3)
*r3 = IPC_GET_ARG3(result);
if (r4)
*r4 = IPC_GET_ARG4(result);
if (r5)
*r5 = IPC_GET_ARG5(result);
return rc;
}
 
/branches/tracing/uspace/lib/libc/generic/vfs/vfs.c
31,7 → 31,7
*/
/** @file
*/
 
#include <vfs/vfs.h>
#include <vfs/canonify.h>
#include <stdlib.h>
49,7 → 49,7
#include <errno.h>
#include <string.h>
#include <ipc/devmap.h>
#include "../../srv/vfs/vfs.h"
#include "../../../srv/vfs/vfs.h"
 
int vfs_phone = -1;
futex_t vfs_phone_futex = FUTEX_INITIALIZER;
57,7 → 57,7
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_len = 0;
size_t cwd_size = 0;
 
char *absolutize(const char *path, size_t *retlen)
{
65,22 → 65,22
char *ncwd_path_nc;
 
futex_down(&cwd_futex);
size_t len = strlen(path);
size_t size = str_size(path);
if (*path != '/') {
if (!cwd_path) {
futex_up(&cwd_futex);
return NULL;
}
ncwd_path_nc = malloc(cwd_len + 1 + len + 1);
ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
if (!ncwd_path_nc) {
futex_up(&cwd_futex);
return NULL;
}
strcpy(ncwd_path_nc, cwd_path);
ncwd_path_nc[cwd_len] = '/';
ncwd_path_nc[cwd_len + 1] = '\0';
str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
ncwd_path_nc[cwd_size] = '/';
ncwd_path_nc[cwd_size + 1] = '\0';
} else {
ncwd_path_nc = malloc(len + 1);
ncwd_path_nc = malloc(size + 1);
if (!ncwd_path_nc) {
futex_up(&cwd_futex);
return NULL;
87,7 → 87,7
}
ncwd_path_nc[0] = '\0';
}
strcat(ncwd_path_nc, path);
str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
ncwd_path = canonify(ncwd_path_nc, retlen);
if (!ncwd_path) {
futex_up(&cwd_futex);
99,7 → 99,7
* the address in ncwd_path need not be the same as ncwd_path_nc, even
* though they both point into the same dynamically allocated buffer.
*/
ncwd_path = strdup(ncwd_path);
ncwd_path = str_dup(ncwd_path);
free(ncwd_path_nc);
if (!ncwd_path) {
futex_up(&cwd_futex);
109,34 → 109,39
return ncwd_path;
}
 
static int vfs_connect(void)
static void vfs_connect(void)
{
if (vfs_phone < 0)
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
return vfs_phone;
while (vfs_phone < 0)
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
}
 
static int device_get_handle(const char *name, dev_handle_t *handle)
static int device_get_handle(const char *name, dev_handle_t *handle,
const unsigned int flags)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
0);
int phone;
if (flags & IPC_FLAG_BLOCKING)
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
else
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
if (phone < 0)
return phone;
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0,
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
&answer);
ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1);
 
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
if (retval != EOK) {
async_wait_for(req, NULL);
ipc_hangup(phone);
return retval;
}
 
async_wait_for(req, &retval);
 
if (handle != NULL)
*handle = -1;
149,7 → 154,8
return retval;
}
 
int mount(const char *fs_name, const char *mp, const char *dev)
int mount(const char *fs_name, const char *mp, const char *dev,
const char *opts, const unsigned int flags)
{
int res;
ipcarg_t rc;
156,28 → 162,30
aid_t req;
dev_handle_t dev_handle;
res = device_get_handle(dev, &dev_handle);
res = device_get_handle(dev, &dev_handle, flags);
if (res != EOK)
return res;
size_t mpa_len;
char *mpa = absolutize(mp, &mpa_len);
size_t mpa_size;
char *mpa = absolutize(mp, &mpa_size);
if (!mpa)
return ENOMEM;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(mpa);
return res;
}
vfs_connect();
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL);
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
futex_up(&vfs_phone_futex);
free(mpa);
return (int) rc;
}
req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL);
rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name));
rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
185,8 → 193,8
free(mpa);
return (int) rc;
}
/* Ask VFS whether it likes fs_name. */
rc = async_req_0_0(vfs_phone, IPC_M_PING);
 
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
194,7 → 202,9
free(mpa);
return (int) rc;
}
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len);
 
/* Ask VFS whether it likes fs_name. */
rc = async_req_0_0(vfs_phone, IPC_M_PING);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
202,38 → 212,32
free(mpa);
return (int) rc;
}
async_wait_for(req, &rc);
async_serialize_end();
futex_up(&vfs_phone_futex);
free(mpa);
return (int) rc;
}
 
static int _open(const char *path, int lflag, int oflag, ...)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
size_t pa_len;
char *pa = absolutize(path, &pa_len);
size_t pa_size;
char *pa = absolutize(path, &pa_size);
if (!pa)
return ENOMEM;
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return res;
}
}
vfs_connect();
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
rc = ipc_data_write_start(vfs_phone, pa, pa_len);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
258,22 → 262,14
 
int close(int fildes)
{
int res;
ipcarg_t rc;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
 
async_serialize_end();
futex_up(&vfs_phone_futex);
282,7 → 278,6
 
ssize_t read(int fildes, void *buf, size_t nbyte)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
289,14 → 284,8
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
316,7 → 305,6
 
ssize_t write(int fildes, const void *buf, size_t nbyte)
{
int res;
ipcarg_t rc;
ipc_call_t answer;
aid_t req;
323,14 → 311,8
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
350,20 → 332,12
 
off_t lseek(int fildes, off_t offset, int whence)
{
int res;
ipcarg_t rc;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
&newoffs);
379,19 → 353,12
 
int ftruncate(int fildes, off_t length)
{
int res;
ipcarg_t rc;
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
return res;
}
}
vfs_connect();
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
async_serialize_end();
futex_up(&vfs_phone_futex);
433,28 → 400,20
 
int mkdir(const char *path, mode_t mode)
{
int res;
ipcarg_t rc;
aid_t req;
size_t pa_len;
char *pa = absolutize(path, &pa_len);
size_t pa_size;
char *pa = absolutize(path, &pa_size);
if (!pa)
return ENOMEM;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return res;
}
}
vfs_connect();
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_len);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
471,28 → 430,20
 
static int _unlink(const char *path, int lflag)
{
int res;
ipcarg_t rc;
aid_t req;
size_t pa_len;
char *pa = absolutize(path, &pa_len);
size_t pa_size;
char *pa = absolutize(path, &pa_size);
if (!pa)
return ENOMEM;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return res;
}
}
vfs_connect();
req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_len);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
519,17 → 470,16
 
int rename(const char *old, const char *new)
{
int res;
ipcarg_t rc;
aid_t req;
size_t olda_len;
char *olda = absolutize(old, &olda_len);
size_t olda_size;
char *olda = absolutize(old, &olda_size);
if (!olda)
return ENOMEM;
 
size_t newa_len;
char *newa = absolutize(new, &newa_len);
size_t newa_size;
char *newa = absolutize(new, &newa_size);
if (!newa) {
free(olda);
return ENOMEM;
537,18 → 487,10
 
futex_down(&vfs_phone_futex);
async_serialize_start();
if (vfs_phone < 0) {
res = vfs_connect();
if (res < 0) {
async_serialize_end();
futex_up(&vfs_phone_futex);
free(olda);
free(newa);
return res;
}
}
vfs_connect();
req = async_send_0(vfs_phone, VFS_RENAME, NULL);
rc = ipc_data_write_start(vfs_phone, olda, olda_len);
rc = ipc_data_write_start(vfs_phone, olda, olda_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
557,7 → 499,7
free(newa);
return (int) rc;
}
rc = ipc_data_write_start(vfs_phone, newa, newa_len);
rc = ipc_data_write_start(vfs_phone, newa, newa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
576,8 → 518,8
 
int chdir(const char *path)
{
size_t pa_len;
char *pa = absolutize(path, &pa_len);
size_t pa_size;
char *pa = absolutize(path, &pa_size);
if (!pa)
return ENOMEM;
 
593,11 → 535,11
cwd_dir = NULL;
free(cwd_path);
cwd_path = NULL;
cwd_len = 0;
cwd_size = 0;
}
cwd_dir = d;
cwd_path = pa;
cwd_len = pa_len;
cwd_size = pa_size;
futex_up(&cwd_futex);
return EOK;
}
607,11 → 549,11
if (!size)
return NULL;
futex_down(&cwd_futex);
if (size < cwd_len + 1) {
if (size < cwd_size + 1) {
futex_up(&cwd_futex);
return NULL;
}
strcpy(buf, cwd_path);
str_cpy(buf, size, cwd_path);
futex_up(&cwd_futex);
return buf;
}
/branches/tracing/uspace/lib/libc/generic/mem.c
0,0 → 1,239
/*
* Copyright (c) 2005 Martin Decky
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <mem.h>
#include <stdlib.h>
#include <sys/types.h>
 
/** Fill memory block with a constant value. */
void *memset(void *dest, int b, size_t n)
{
char *pb;
unsigned long *pw;
size_t word_size;
size_t n_words;
 
unsigned long pattern;
size_t i;
size_t fill;
 
/* Fill initial segment. */
word_size = sizeof(unsigned long);
fill = word_size - ((uintptr_t) dest & (word_size - 1));
if (fill > n) fill = n;
 
pb = dest;
 
i = fill;
while (i-- != 0)
*pb++ = b;
 
/* Compute remaining size. */
n -= fill;
if (n == 0) return dest;
 
n_words = n / word_size;
n = n % word_size;
pw = (unsigned long *) pb;
 
/* Create word-sized pattern for aligned segment. */
pattern = 0;
i = word_size;
while (i-- != 0)
pattern = (pattern << 8) | (uint8_t) b;
 
/* Fill aligned segment. */
i = n_words;
while (i-- != 0)
*pw++ = pattern;
 
pb = (char *) pw;
 
/* Fill final segment. */
i = n;
while (i-- != 0)
*pb++ = b;
 
return dest;
}
 
struct along {
unsigned long n;
} __attribute__ ((packed));
 
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
{
int i, j;
struct along *adst = dst;
const struct along *asrc = src;
 
for (i = 0; i < n / sizeof(unsigned long); i++)
adst[i].n = asrc[i].n;
for (j = 0; j < n % sizeof(unsigned long); j++)
((unsigned char *) (((unsigned long *) dst) + i))[j] =
((unsigned char *) (((unsigned long *) src) + i))[j];
return (char *) dst;
}
 
/** Copy memory block. */
void *memcpy(void *dst, const void *src, size_t n)
{
size_t i;
size_t mod, fill;
size_t word_size;
size_t n_words;
 
const unsigned long *srcw;
unsigned long *dstw;
const uint8_t *srcb;
uint8_t *dstb;
 
word_size = sizeof(unsigned long);
 
/*
* Are source and destination addresses congruent modulo word_size?
* If not, use unaligned_memcpy().
*/
 
if (((uintptr_t) dst & (word_size - 1)) !=
((uintptr_t) src & (word_size - 1)))
return unaligned_memcpy(dst, src, n);
 
/*
* mod is the address modulo word size. fill is the length of the
* initial buffer segment before the first word boundary.
* If the buffer is very short, use unaligned_memcpy(), too.
*/
 
mod = (uintptr_t) dst & (word_size - 1);
fill = word_size - mod;
if (fill > n) fill = n;
 
/* Copy the initial segment. */
 
srcb = src;
dstb = dst;
 
i = fill;
while (i-- != 0)
*dstb++ = *srcb++;
 
/* Compute remaining length. */
 
n -= fill;
if (n == 0) return dst;
 
/* Pointers to aligned segment. */
 
dstw = (unsigned long *) dstb;
srcw = (const unsigned long *) srcb;
 
n_words = n / word_size; /* Number of whole words to copy. */
n -= n_words * word_size; /* Remaining bytes at the end. */
 
/* "Fast" copy. */
i = n_words;
while (i-- != 0)
*dstw++ = *srcw++;
 
/*
* Copy the rest.
*/
 
srcb = (const uint8_t *) srcw;
dstb = (uint8_t *) dstw;
 
i = n;
while (i-- != 0)
*dstb++ = *srcb++;
 
return dst;
}
 
/** Move memory block with possible overlapping. */
void *memmove(void *dst, const void *src, size_t n)
{
const uint8_t *sp;
uint8_t *dp;
 
/* Nothing to do? */
if (src == dst)
return dst;
 
/* Non-overlapping? */
if (dst >= src + n || src >= dst + n) {
return memcpy(dst, src, n);
}
 
/* Which direction? */
if (src > dst) {
/* Forwards. */
sp = src;
dp = dst;
 
while (n-- != 0)
*dp++ = *sp++;
} else {
/* Backwards. */
sp = src + (n - 1);
dp = dst + (n - 1);
 
while (n-- != 0)
*dp-- = *sp--;
}
 
return dst;
}
 
/** Compare two memory areas.
*
* @param s1 Pointer to the first area to compare.
* @param s2 Pointer to the second area to compare.
* @param len Size of the first area in bytes. Both areas must have
* the same length.
* @return If len is 0, return zero. If the areas match, return
* zero. Otherwise return non-zero.
*/
int bcmp(const char *s1, const char *s2, size_t len)
{
for (; len && *s1++ == *s2++; len--)
;
return len;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/event.c
0,0 → 1,57
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
* @}
*/
 
/** @addtogroup libc
*/
/** @file
*/
 
#include <libc.h>
#include <event.h>
#include <kernel/ipc/event_types.h>
#include <ipc/ipc.h>
 
/** Subscribe for event notifications.
*
* @param evno Event number.
* @param method Use this method for notifying me.
*
* @return Value returned by the kernel.
*/
int event_subscribe(event_type_t e, ipcarg_t method)
{
return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/io/stdio.c
0,0 → 1,278
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/**
* @file
* @brief ANSI C Stream I/O.
*/
 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <bool.h>
#include <stdio.h>
 
FILE *stdin, *stdout, *stderr;
 
/**
* Open a stream.
*
* @param file_name Name of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*/
FILE *fopen(const char *file_name, const char *mode)
{
FILE *f;
int flags;
bool plus;
const char *mp;
 
/* Parse mode except first character. */
 
mp = mode;
if (*mp++ == '\0') {
errno = EINVAL;
return NULL;
}
 
if (*mp == 'b' || *mp == 't') ++mp;
 
if (*mp == '+') {
++mp;
plus = true;
} else {
plus = false;
}
 
if (*mp != '\0') {
errno = EINVAL;
return NULL;
}
 
/* Parse first character of mode and determine flags for open(). */
 
switch (mode[0]) {
case 'r':
flags = plus ? O_RDWR : O_RDONLY;
break;
case 'w':
flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
break;
case 'a':
/* TODO: a+ must read from beginning, append to the end. */
if (plus) {
errno = ENOTSUP;
return NULL;
}
flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
default:
errno = EINVAL;
return NULL;
}
 
/* Open file. */
f = malloc(sizeof(FILE));
if (f == NULL) {
errno = ENOMEM;
return NULL;
}
 
f->fd = open(file_name, flags, 0666);
if (f->fd < 0) {
free(f);
return NULL; /* errno was set by open() */
}
 
f->error = 0;
f->eof = 0;
 
return f;
}
 
/** Close a stream.
*
* @param f Pointer to stream.
* @return 0 on success, EOF on error.
*/
int fclose(FILE *f)
{
int rc;
 
rc = close(f->fd);
free(f);
 
if (rc != 0)
return EOF; /* errno was set by close() */
 
return 0;
}
 
/** Read from a stream.
*
* @param buf Destination buffer.
* @param size Size of each record.
* @param nmemb Number of records to read.
* @param f Pointer to the stream.
*/
size_t fread(void *buf, size_t size, size_t nmemb, FILE *f)
{
size_t left, done, n;
 
left = size * nmemb;
done = 0;
 
while (left > 0 && !f->error && !f->eof) {
n = read(f->fd, buf + done, left);
 
if (n < 0) {
f->error = 1;
} else if (n == 0) {
f->eof = 1;
} else {
left -= n;
done += n;
}
}
 
return done / size;
}
 
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param f Pointer to the stream.
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f)
{
size_t left, done, n;
 
left = size * nmemb;
done = 0;
 
while (left > 0 && !f->error) {
n = write(f->fd, buf + done, left);
 
if (n <= 0) {
f->error = 1;
} else {
left -= n;
done += n;
}
}
 
return done / size;
}
 
/** Return the end-of-file indicator of a stream. */
int feof(FILE *f)
{
return f->eof;
}
 
/** Return the error indicator of a stream. */
int ferror(FILE *f)
{
return f->error;
}
 
/** Clear the error and end-of-file indicators of a stream. */
void clearerr(FILE *f)
{
f->eof = 0;
f->error = 0;
}
 
/** Read character from a stream. */
int fgetc(FILE *f)
{
unsigned char c;
size_t n;
 
n = fread(&c, sizeof(c), 1, f);
if (n < 1) return EOF;
 
return (int) c;
}
 
/** Write character to a stream. */
int fputc(int c, FILE *f)
{
unsigned char cc;
size_t n;
 
cc = (unsigned char) c;
n = fwrite(&cc, sizeof(cc), 1, f);
if (n < 1) return EOF;
 
return (int) cc;
}
 
/** Write string to a stream. */
int fputs(const char *s, FILE *f)
{
int rc;
 
rc = 0;
 
while (*s && rc >= 0) {
rc = fputc(*s++, f);
}
 
if (rc < 0) return EOF;
 
return 0;
}
 
/** Seek to position in stream. */
int fseek(FILE *f, long offset, int origin)
{
off_t rc;
 
rc = lseek(f->fd, offset, origin);
if (rc == (off_t) (-1)) {
/* errno has been set by lseek. */
return -1;
}
 
f->eof = 0;
 
return 0;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/io/io.c
36,6 → 36,9
#include <unistd.h>
#include <stdio.h>
#include <io/io.h>
#include <string.h>
#include <errno.h>
#include <console.h>
 
const static char nl = '\n';
 
47,8 → 50,9
return putnchars("(NULL)", 6);
for (count = 0; str[count] != 0; count++);
if (write_stdout((void *) str, count) == count) {
if (write_stdout(&nl, 1) == 1)
if (console_write((void *) str, count) == count) {
if (console_write(&nl, 1) == 1)
return 0;
}
62,7 → 66,7
*/
int putnchars(const char *buf, size_t count)
{
if (write_stdout((void *) buf, count) == count)
if (console_write((void *) buf, count) == count)
return 0;
return EOF;
79,7 → 83,7
return putnchars("(NULL)", 6);
 
for (count = 0; str[count] != 0; count++);
if (write_stdout((void *) str, count) == count)
if (console_write((void *) str, count) == count)
return 0;
return EOF;
87,10 → 91,16
 
int putchar(int c)
{
unsigned char ch = c;
if (write_stdout((void *) &ch, 1) == 1)
char buf[STR_BOUNDS(1)];
size_t offs;
 
offs = 0;
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK)
return EOF;
 
if (console_write((void *) buf, offs) == offs)
return c;
 
return EOF;
}
 
97,6 → 107,8
int getchar(void)
{
unsigned char c;
console_flush();
if (read_stdin((void *) &c, 1) == 1)
return c;
103,5 → 115,13
return EOF;
}
 
int fflush(FILE *f)
{
/* Dummy implementation */
(void) f;
console_flush();
return 0;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/io/vprintf.c
38,14 → 38,45
#include <io/printf_core.h>
#include <futex.h>
#include <async.h>
#include <console.h>
 
static atomic_t printf_futex = FUTEX_INITIALIZER;
 
static int vprintf_write(const char *str, size_t count, void *unused)
static int vprintf_str_write(const char *str, size_t size, void *data)
{
return write_stdout(str, count);
size_t offset = 0;
size_t prev;
count_t chars = 0;
while (offset < size) {
prev = offset;
str_decode(str, &offset, size);
console_write(str + prev, offset - prev);
chars++;
}
return chars;
}
 
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
{
size_t offset = 0;
size_t boff;
count_t chars = 0;
char buf[4];
while (offset < size) {
boff = 0;
chr_encode(str[chars], buf, &boff, 4);
console_write(buf, boff);
chars++;
offset += sizeof(wchar_t);
}
return chars;
}
 
 
/** Print formatted text.
* @param fmt format string
* @param ap format parameters
54,7 → 85,8
int vprintf(const char *fmt, va_list ap)
{
struct printf_spec ps = {
(int (*)(void *, size_t, void *)) vprintf_write,
vprintf_str_write,
vprintf_wstr_write,
NULL
};
/*
/branches/tracing/uspace/lib/libc/generic/io/fprintf.c
0,0 → 1,77
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/**
* @file
* @brief fprintf, vfprintf
*/
 
#include <stdio.h>
#include <sys/types.h>
#include <io/printf_core.h>
 
static int vfprintf_str_write(const char *s, size_t size, void *f)
{
/* FIXME: Should return number of characters? */
return fwrite(s, 1, size, (FILE *) f);
}
 
static int vfprintf_wstr_write(const char *s, size_t size, void *f)
{
/* TODO */
return size;
}
 
int vfprintf(FILE *f, const char *fmt, va_list ap)
{
struct printf_spec ps = {
vfprintf_str_write,
vfprintf_wstr_write,
(void *) f
};
 
return printf_core(fmt, &ps, ap);
}
 
int fprintf(FILE *f, const char *fmt, ...)
{
int rv;
va_list args;
 
va_start(args, fmt);
rv = vfprintf(f, fmt, args);
va_end(args);
 
return rv;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/io/vsnprintf.c
36,87 → 36,145
#include <stdio.h>
#include <string.h>
#include <io/printf_core.h>
#include <errno.h>
 
struct vsnprintf_data {
size_t size; /* total space for string */
size_t len; /* count of currently used characters */
char *string; /* destination string */
};
typedef struct {
size_t size; /* Total size of the buffer (in bytes) */
size_t len; /* Number of already used bytes */
char *dst; /* Destination */
} vsnprintf_data_t;
 
/** Write string to given buffer.
* Write at most data->size characters including trailing zero. According to C99
* has snprintf to return number of characters that would have been written if
* enough space had been available. Hence the return value is not number of
* really printed characters but size of input string. Number of really used
* characters is stored in data->len.
*
* @param str Source string to print.
* @param count Size of the source string.
* @param data Structure with destination string, counter of used space
* and total string size.
* @return Number of characters to print (not characters really
* printed!)
* Write at most data->size plain characters including trailing zero.
* According to C99, snprintf() has to return number of characters that
* would have been written if enough space had been available. Hence
* the return value is not the number of actually printed characters
* but size of the input string.
*
* @param str Source string to print.
* @param size Number of plain characters in str.
* @param data Structure describing destination string, counter
* of used space and total string size.
*
* @return Number of characters to print (not characters actually
* printed).
*
*/
static int
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
static int vsnprintf_str_write(const char *str, size_t size, vsnprintf_data_t *data)
{
size_t i;
i = data->size - data->len;
 
if (i == 0) {
return count;
}
size_t left = data->size - data->len;
if (i == 1) {
/*
* We have only one free byte left in buffer => write there
* trailing zero.
if (left == 0)
return ((int) size);
if (left == 1) {
/* We have only one free byte left in buffer
* -> store trailing zero
*/
data->string[data->size - 1] = 0;
data->dst[data->size - 1] = 0;
data->len = data->size;
return count;
return ((int) size);
}
if (i <= count) {
/*
* We have not enought space for whole string with the trailing
* zero => print only a part of string.
if (left <= size) {
/* We do not have enough space for the whole string
* with the trailing zero => print only a part
* of string
*/
memcpy((void *)(data->string + data->len), (void *)str, i - 1);
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
index_t index = 0;
while (index < size) {
wchar_t uc = str_decode(str, &index, size);
if (chr_encode(uc, data->dst, &data->len, data->size - 1) != EOK)
break;
}
/* Put trailing zero at end, but not count it
* into data->len so it could be rewritten next time
*/
data->dst[data->len] = 0;
return ((int) size);
}
/* Buffer is big enought to print whole string */
memcpy((void *)(data->string + data->len), (void *)str, count);
data->len += count;
/*
* Put trailing zero at end, but not count it into data->len so it could
* be rewritten next time.
/* Buffer is big enought to print the whole string */
memcpy((void *)(data->dst + data->len), (void *) str, size);
data->len += size;
/* Put trailing zero at end, but not count it
* into data->len so it could be rewritten next time
*/
data->string[data->len] = 0;
data->dst[data->len] = 0;
return ((int) size);
}
 
return count;
/** Write wide string to given buffer.
*
* Write at most data->size plain characters including trailing zero.
* According to C99, snprintf() has to return number of characters that
* would have been written if enough space had been available. Hence
* the return value is not the number of actually printed characters
* but size of the input string.
*
* @param str Source wide string to print.
* @param size Number of bytes in str.
* @param data Structure describing destination string, counter
* of used space and total string size.
*
* @return Number of wide characters to print (not characters actually
* printed).
*
*/
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
{
index_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
if (left == 0)
return ((int) size);
if (left == 1) {
/* We have only one free byte left in buffer
* -> store trailing zero
*/
data->dst[data->size - 1] = 0;
data->len = data->size;
return ((int) size);
}
if (chr_encode(str[index], data->dst, &data->len, data->size - 1) != EOK)
break;
index++;
}
/* Put trailing zero at end, but not count it
* into data->len so it could be rewritten next time
*/
data->dst[data->len] = 0;
return ((int) size);
}
 
/** Print formatted to the given buffer with limited size.
* @param str Buffer.
* @param size Bffer size.
* @param fmt Format string.
* \see For more details about format string see printf_core.
*/
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
struct vsnprintf_data data = {size, 0, str};
struct printf_spec ps = {
(int(*)(void *, size_t, void *)) vsnprintf_write,
vsnprintf_data_t data = {
size,
0,
str
};
printf_spec_t ps = {
(int(*) (const char *, size_t, void *)) vsnprintf_str_write,
(int(*) (const wchar_t *, size_t, void *)) vsnprintf_wstr_write,
&data
};
 
/*
* Print 0 at end of string - fix the case that nothing will be printed.
*/
/* Print 0 at end of string - fix the case that nothing will be printed */
if (size > 0)
str[0] = 0;
/branches/tracing/uspace/lib/libc/generic/io/printf_core.c
1,6 → 1,7
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
27,12 → 28,12
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
/** @addtogroup generic
* @{
*/
/**
* @file
* @brief Printing functions.
* @brief Printing functions.
*/
 
#include <unistd.h>
41,20 → 42,30
#include <ctype.h>
#include <string.h>
 
#define __PRINTF_FLAG_PREFIX 0x00000001 /**< show prefixes 0x or 0*/
#define __PRINTF_FLAG_SIGNED 0x00000002 /**< signed / unsigned number */
#define __PRINTF_FLAG_ZEROPADDED 0x00000004 /**< print leading zeroes */
#define __PRINTF_FLAG_LEFTALIGNED 0x00000010 /**< align to left */
#define __PRINTF_FLAG_SHOWPLUS 0x00000020 /**< always show + sign */
#define __PRINTF_FLAG_SPACESIGN 0x00000040 /**< print space instead of plus */
#define __PRINTF_FLAG_BIGCHARS 0x00000080 /**< show big characters */
#define __PRINTF_FLAG_NEGATIVE 0x00000100 /**< number has - sign */
/** show prefixes 0x or 0 */
#define __PRINTF_FLAG_PREFIX 0x00000001
/** signed / unsigned number */
#define __PRINTF_FLAG_SIGNED 0x00000002
/** print leading zeroes */
#define __PRINTF_FLAG_ZEROPADDED 0x00000004
/** align to left */
#define __PRINTF_FLAG_LEFTALIGNED 0x00000010
/** always show + sign */
#define __PRINTF_FLAG_SHOWPLUS 0x00000020
/** print space instead of plus */
#define __PRINTF_FLAG_SPACESIGN 0x00000040
/** show big characters */
#define __PRINTF_FLAG_BIGCHARS 0x00000080
/** number has - sign */
#define __PRINTF_FLAG_NEGATIVE 0x00000100
 
#define PRINT_NUMBER_BUFFER_SIZE (64+5) /**< Buffer big enought for 64 bit number
* printed in base 2, sign, prefix and
* 0 to terminate string.. (last one is only for better testing
* end of buffer by zero-filling subroutine)
*/
/**
* Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0
* to terminate string... (last one is only for better testing end of buffer by
* zero-filling subroutine)
*/
#define PRINT_NUMBER_BUFFER_SIZE (64 + 5)
 
/** Enumeration of possible arguments types.
*/
typedef enum {
63,171 → 74,299
PrintfQualifierInt,
PrintfQualifierLong,
PrintfQualifierLongLong,
PrintfQualifierSizeT,
PrintfQualifierPointer
} qualifier_t;
 
static char digits_small[] = "0123456789abcdef"; /**< Small hexadecimal characters */
static char digits_big[] = "0123456789ABCDEF"; /**< Big hexadecimal characters */
static char nullstr[] = "(NULL)";
static char digits_small[] = "0123456789abcdef";
static char digits_big[] = "0123456789ABCDEF";
static char invalch = U_SPECIAL;
 
/** Print count chars from buffer without adding newline
* @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
* @param count
* @param ps output method and its data
* @return number of printed characters
/** Print one or more characters without adding newline.
*
* @param buf Buffer holding characters with size of
* at least size bytes. NULL is not allowed!
* @param size Size of the buffer in bytes.
* @param ps Output method and its data.
*
* @return Number of characters printed.
*
*/
static int printf_putnchars(const char * buf, size_t count,
struct printf_spec *ps)
static int printf_putnchars(const char *buf, size_t size,
printf_spec_t *ps)
{
return ps->write((void *)buf, count, ps->data);
return ps->str_write((void *) buf, size, ps->data);
}
 
/** Print string without added newline
* @param str string to print
* @param ps write function specification and support data
* @return number of printed characters
/** Print one or more wide characters without adding newline.
*
* @param buf Buffer holding wide characters with size of
* at least size bytes. NULL is not allowed!
* @param size Size of the buffer in bytes.
* @param ps Output method and its data.
*
* @return Number of wide characters printed.
*
*/
static int printf_putstr(const char * str, struct printf_spec *ps)
static int printf_wputnchars(const wchar_t *buf, size_t size,
printf_spec_t *ps)
{
size_t count;
return ps->wstr_write((void *) buf, size, ps->data);
}
 
/** Print string without adding a newline.
*
* @param str String to print.
* @param ps Write function specification and support data.
*
* @return Number of characters printed.
*
*/
static int printf_putstr(const char *str, printf_spec_t *ps)
{
if (str == NULL)
return printf_putnchars(nullstr, str_size(nullstr), ps);
if (str == NULL)
return printf_putnchars("(NULL)", 6, ps);
return ps->str_write((void *) str, str_size(str), ps->data);
}
 
count = strlen(str);
 
return ps->write((void *) str, count, ps->data);
/** Print one ASCII character.
*
* @param c ASCII character to be printed.
* @param ps Output method.
*
* @return Number of characters printed.
*
*/
static int printf_putchar(const char ch, printf_spec_t *ps)
{
if (!ascii_check(ch))
return ps->str_write((void *) &invalch, 1, ps->data);
return ps->str_write(&ch, 1, ps->data);
}
 
/** Print one character to output
* @param c one character
* @param ps output method
* @return number of printed characters
/** Print one wide character.
*
* @param c Wide character to be printed.
* @param ps Output method.
*
* @return Number of characters printed.
*
*/
static int printf_putchar(int c, struct printf_spec *ps)
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
{
unsigned char ch = c;
if (!chr_check(ch))
return ps->str_write((void *) &invalch, 1, ps->data);
return ps->write((void *) &ch, 1, ps->data);
return ps->wstr_write(&ch, sizeof(wchar_t), ps->data);
}
 
/** Print one formatted character
* @param c character to print
* @param width
* @param flags
* @return number of printed characters
/** Print one formatted ASCII character.
*
* @param ch Character to print.
* @param width Width modifier.
* @param flags Flags that change the way the character is printed.
*
* @return Number of characters printed, negative value on failure.
*
*/
static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
int counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
/*
* One space is consumed by the character itself, hence the
* predecrement.
*/
while (--width > 0) {
if (printf_putchar(' ', ps) > 0)
++counter;
/*
* One space is consumed by the character itself, hence
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
counter++;
}
}
if (printf_putchar(c, ps) > 0)
if (printf_putchar(ch, ps) > 0)
counter++;
/*
* One space is consumed by the character itself, hence the
* predecrement.
*/
while (--width > 0) {
/*
* One space is consumed by the character itself, hence
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
++counter;
counter++;
}
return ++counter;
return (int) (counter + 1);
}
 
/** Print one string
* @param s string
* @param width
* @param precision
* @param flags
* @return number of printed characters
/** Print one formatted wide character.
*
* @param ch Character to print.
* @param width Width modifier.
* @param flags Flags that change the way the character is printed.
*
* @return Number of characters printed, negative value on failure.
*
*/
static int print_string(char *s, int width, int precision, uint64_t flags,
struct printf_spec *ps)
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
int counter = 0;
size_t size;
int retval;
 
if (s == NULL) {
return printf_putstr("(NULL)", ps);
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
* One space is consumed by the character itself, hence
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
counter++;
}
}
size = strlen(s);
if (printf_putwchar(ch, ps) > 0)
counter++;
while (--width > 0) {
/*
* One space is consumed by the character itself, hence
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
counter++;
}
return (int) (counter + 1);
}
 
/* print leading spaces */
/** Print string.
*
* @param str String to be printed.
* @param width Width modifier.
* @param precision Precision modifier.
* @param flags Flags that modify the way the string is printed.
*
* @return Number of characters printed, negative value on failure.
*/
static int print_str(char *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
{
if (str == NULL)
return printf_putstr(nullstr, ps);
 
if (precision == 0)
precision = size;
/* Print leading spaces. */
count_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
}
 
if ((retval = printf_putnchars(s, size < precision ? size : precision,
ps)) < 0) {
/* Part of @a str fitting into the alloted space. */
int retval;
size_t size = str_lsize(str, precision);
if ((retval = printf_putnchars(str, size, ps)) < 0)
return -counter;
 
counter += retval;
 
/* Right padding */
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
 
counter += retval;
return ((int) counter);
 
}
 
/** Print wide string.
*
* @param str Wide string to be printed.
* @param width Width modifier.
* @param precision Precision modifier.
* @param flags Flags that modify the way the string is printed.
*
* @return Number of wide characters printed, negative value on failure.
*/
static int print_wstr(wchar_t *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
{
if (str == NULL)
return printf_putstr(nullstr, ps);
if (*str == U_BOM)
str++;
/* Print leading spaces. */
size_t strw = wstr_length(str);
if (precision == 0)
precision = strw;
/* Left padding */
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
}
/* Part of @a wstr fitting into the alloted space. */
int retval;
size_t size = wstr_lsize(str, precision);
if ((retval = printf_wputnchars(str, size, ps)) < 0)
return -counter;
counter += retval;
/* Right padding */
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
++counter;
if (printf_putchar(' ', ps) == 1)
counter++;
}
return counter;
 
return ((int) counter);
}
 
 
/** Print number in given base
/** Print a number in a given base.
*
* Print significant digits of a number in given
* base.
* Print significant digits of a number in given base.
*
* @param num Number to print.
* @param width
* @param precision
* @param base Base to print the number in (should
* be in range 2 .. 16).
* @param flags output modifiers
* @return number of printed characters
* @param num Number to print.
* @param width Width modifier.
* @param precision Precision modifier.
* @param base Base to print the number in (must be between 2 and 16).
* @param flags Flags that modify the way the number is printed.
*
* @return Number of characters printed.
*
*/
static int print_number(uint64_t num, int width, int precision, int base,
uint64_t flags, struct printf_spec *ps)
uint32_t flags, printf_spec_t *ps)
{
char *digits = digits_small;
char d[PRINT_NUMBER_BUFFER_SIZE]; /* this is good enough even for
* base == 2, prefix and sign */
char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
int size = 0; /* size of number with all prefixes and signs */
int number_size; /* size of plain number */
char sgn;
int retval;
int counter = 0;
char *digits;
if (flags & __PRINTF_FLAG_BIGCHARS)
digits = digits_big;
else
digits = digits_small;
if (flags & __PRINTF_FLAG_BIGCHARS)
digits = digits_big;
char data[PRINT_NUMBER_BUFFER_SIZE];
char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1];
*ptr-- = 0; /* Put zero at end of string */
 
/* Size of number with all prefixes and signs */
int size = 0;
/* Put zero at end of string */
*ptr-- = 0;
if (num == 0) {
*ptr-- = '0';
size++;
238,15 → 377,17
} while (num /= base);
}
number_size = size;
 
/* Size of plain number */
int number_size = size;
/*
* Collect sum of all prefixes/signs/... to calculate padding and
* leading zeroes
* Collect the sum of all prefixes/signs/etc. to calculate padding and
* leading zeroes.
*/
if (flags & __PRINTF_FLAG_PREFIX) {
switch(base) {
case 2: /* Binary formating is not standard, but usefull */
case 2:
/* Binary formating is not standard, but usefull */
size += 2;
break;
case 8:
257,8 → 398,8
break;
}
}
 
sgn = 0;
char sgn = 0;
if (flags & __PRINTF_FLAG_SIGNED) {
if (flags & __PRINTF_FLAG_NEGATIVE) {
sgn = '-';
271,47 → 412,46
size++;
}
}
 
if (flags & __PRINTF_FLAG_LEFTALIGNED) {
if (flags & __PRINTF_FLAG_LEFTALIGNED)
flags &= ~__PRINTF_FLAG_ZEROPADDED;
}
 
/*
* If number is leftaligned or precision is specified then zeropadding
* is ignored.
* If the number is left-aligned or precision is specified then
* padding with zeros is ignored.
*/
if (flags & __PRINTF_FLAG_ZEROPADDED) {
if ((precision == 0) && (width > size)) {
if ((precision == 0) && (width > size))
precision = width - size + number_size;
}
}
 
/* print leading spaces */
 
/* We must print whole number not only a part. */
if (number_size > precision)
/* Print leading spaces */
if (number_size > precision) {
/* Print the whole number, not only a part */
precision = number_size;
 
}
width -= precision + size - number_size;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
}
/* print sign */
/* Print sign */
if (sgn) {
if (printf_putchar(sgn, ps) == 1)
counter++;
}
/* print prefix */
/* Print prefix */
if (flags & __PRINTF_FLAG_PREFIX) {
switch(base) {
case 2: /* Binary formating is not standard, but usefull */
case 2:
/* Binary formating is not standard, but usefull */
if (printf_putchar('0', ps) == 1)
counter++;
if (flags & __PRINTF_FLAG_BIGCHARS) {
339,152 → 479,154
break;
}
}
 
/* print leading zeroes */
/* Print leading zeroes */
precision -= number_size;
while (precision-- > 0) {
while (precision-- > 0) {
if (printf_putchar('0', ps) == 1)
counter++;
}
 
/* print number itself */
 
if ((retval = printf_putstr(++ptr, ps)) > 0) {
/* Print the number itself */
int retval;
if ((retval = printf_putstr(++ptr, ps)) > 0)
counter += retval;
}
/* print ending spaces */
/* Print tailing spaces */
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
 
return counter;
return ((int) counter);
}
 
 
/** Print formatted string.
*
* Print string formatted according to the fmt parameter and variadic arguments.
* Each formatting directive must have the following form:
*
* \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
*
* \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
*
* FLAGS:@n
* - "#" Force to print prefix.
* For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and
* 0X and for conversion \%b the prefix is 0b.
* - "#" Force to print prefix. For \%o conversion, the prefix is 0, for
* \%x and \%X prefixes are 0x and 0X and for conversion \%b the
* prefix is 0b.
*
* - "-" Align to left.
* - "-" Align to left.
*
* - "+" Print positive sign just as negative.
* - "+" Print positive sign just as negative.
*
* - " " If the printed number is positive and "+" flag is not set,
* print space in place of sign.
* - " " If the printed number is positive and "+" flag is not set,
* print space in place of sign.
*
* - "0" Print 0 as padding instead of spaces. Zeroes are placed between
* sign and the rest of the number. This flag is ignored if "-"
* flag is specified.
*
* - "0" Print 0 as padding instead of spaces. Zeroes are placed between
* sign and the rest of the number. This flag is ignored if "-"
* flag is specified.
*
* WIDTH:@n
* - Specify minimal width of printed argument. If it is bigger, width is
* ignored. If width is specified with a "*" character instead of number,
* width is taken from parameter list. And integer parameter is expected
* before parameter for processed conversion specification. If this value
* is negative its absolute value is taken and the "-" flag is set.
* - Specify the minimal width of a printed argument. If it is bigger,
* width is ignored. If width is specified with a "*" character instead of
* number, width is taken from parameter list. And integer parameter is
* expected before parameter for processed conversion specification. If
* this value is negative its absolute value is taken and the "-" flag is
* set.
*
* PRECISION:@n
* - Value precision. For numbers it specifies minimum valid numbers.
* Smaller numbers are printed with leading zeroes. Bigger numbers are
* not affected. Strings with more than precision characters are cut off.
* Just as with width, an "*" can be used used instead of a number. An
* integer value is then expected in parameters. When both width and
* precision are specified using "*", the first parameter is used for
* width and the second one for precision.
*
* - Value precision. For numbers it specifies minimum valid numbers.
* Smaller numbers are printed with leading zeroes. Bigger numbers are not
* affected. Strings with more than precision characters are cut off. Just
* as with width, an "*" can be used used instead of a number. An integer
* value is then expected in parameters. When both width and precision are
* specified using "*", the first parameter is used for width and the
* second one for precision.
*
* TYPE:@n
* - "hh" Signed or unsigned char.@n
* - "h" Signed or usigned short.@n
* - "" Signed or usigned int (default value).@n
* - "l" Signed or usigned long int.@n
* - "ll" Signed or usigned long long int.@n
* - "z" Type size_t.@n
*
*
* - "hh" Signed or unsigned char.@n
* - "h" Signed or unsigned short.@n
* - "" Signed or unsigned int (default value).@n
* - "l" Signed or unsigned long int.@n
* If conversion is "c", the character is wchar_t (wide character).@n
* If conversion is "s", the string is wchar_t * (wide string).@n
* - "ll" Signed or unsigned long long int.@n
*
* CONVERSION:@n
* - % Print percentile character itself.
* - % Print percentile character itself.
*
* - c Print single character.
* - c Print single character. The character is expected to be plain
* ASCII (e.g. only values 0 .. 127 are valid).@n
* If type is "l", then the character is expected to be wide character
* (e.g. values 0 .. 0x10ffff are valid).
*
* - s Print zero terminated string. If a NULL value is passed as
* value, "(NULL)" is printed instead.
*
* - P, p Print value of a pointer. Void * value is expected and it is
* printed in hexadecimal notation with prefix (as with '\%#X' or
* '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers).
* - s Print zero terminated string. If a NULL value is passed as
* value, "(NULL)" is printed instead.@n
* If type is "l", then the string is expected to be wide string.
*
* - b Print value as unsigned binary number. Prefix is not printed by
* default. (Nonstandard extension.)
*
* - o Print value as unsigned octal number. Prefix is not printed by
* default.
* - P, p Print value of a pointer. Void * value is expected and it is
* printed in hexadecimal notation with prefix (as with \%#X / \%#x
* for 32-bit or \%#X / \%#x for 64-bit long pointers).
*
* - d, i Print signed decimal number. There is no difference between d
* and i conversion.
* - b Print value as unsigned binary number. Prefix is not printed by
* default. (Nonstandard extension.)
*
* - u Print unsigned decimal number.
* - o Print value as unsigned octal number. Prefix is not printed by
* default.
*
* - X, x Print hexadecimal number with upper- or lower-case. Prefix is
* not printed by default.
*
* All other characters from fmt except the formatting directives are printed in
* - d, i Print signed decimal number. There is no difference between d
* and i conversion.
*
* - u Print unsigned decimal number.
*
* - X, x Print hexadecimal number with upper- or lower-case. Prefix is
* not printed by default.
*
* All other characters from fmt except the formatting directives are printed
* verbatim.
*
* @param fmt Formatting NULL terminated string.
* @return Number of printed characters or negative value on failure.
* @param fmt Format NULL-terminated string.
*
* @return Number of characters printed, negative value on failure.
*
*/
int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
{
/* i is the index of the currently processed char from fmt */
int i = 0;
/* j is the index to the first not printed nonformating character */
int j = 0;
 
int end;
int counter; /* counter of printed characters */
int retval; /* used to store return values from called functions */
char c;
qualifier_t qualifier; /* type of argument */
int base; /* base in which will be a numeric parameter printed */
uint64_t number; /* argument value */
size_t size; /* byte size of integer parameter */
int width, precision;
uint64_t flags;
size_t i; /* Index of the currently processed character from fmt */
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
counter = 0;
count_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while ((c = fmt[i])) {
/* control character */
if (c == '%' ) {
/* print common characters if any processed */
while (true) {
i = nxt;
wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 0)
break;
/* Control character */
if (uc == '%') {
/* Print common characters if any processed */
if (i > j) {
if ((retval = printf_putnchars(&fmt[j],
(size_t)(i - j), ps)) < 0) { /* error */
goto minus_out;
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
/* Error */
counter = -counter;
goto out;
}
counter += retval;
}
j = i;
/* parse modifiers */
flags = 0;
end = 0;
/* Parse modifiers */
uint32_t flags = 0;
bool end = false;
do {
++i;
switch (c = fmt[i]) {
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
switch (uc) {
case '#':
flags |= __PRINTF_FLAG_PREFIX;
break;
501,114 → 643,145
flags |= __PRINTF_FLAG_ZEROPADDED;
break;
default:
end = 1;
};
} while (end == 0);
end = true;
};
} while (!end);
/* width & '*' operator */
width = 0;
if (isdigit(fmt[i])) {
while (isdigit(fmt[i])) {
/* Width & '*' operator */
int width = 0;
if (isdigit(uc)) {
while (true) {
width *= 10;
width += fmt[i++] - '0';
width += uc - '0';
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 0)
break;
if (!isdigit(uc))
break;
}
} else if (fmt[i] == '*') {
/* get width value from argument list*/
i++;
width = (int)va_arg(ap, int);
} else if (uc == '*') {
/* Get width value from argument list */
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
width = (int) va_arg(ap, int);
if (width < 0) {
/* negative width sets '-' flag */
/* Negative width sets '-' flag */
width *= -1;
flags |= __PRINTF_FLAG_LEFTALIGNED;
}
}
/* precision and '*' operator */
precision = 0;
if (fmt[i] == '.') {
++i;
if (isdigit(fmt[i])) {
while (isdigit(fmt[i])) {
/* Precision and '*' operator */
int precision = 0;
if (uc == '.') {
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (isdigit(uc)) {
while (true) {
precision *= 10;
precision += fmt[i++] - '0';
precision += uc - '0';
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 0)
break;
if (!isdigit(uc))
break;
}
} else if (fmt[i] == '*') {
/* get precision value from argument */
i++;
precision = (int)va_arg(ap, int);
} else if (uc == '*') {
/* Get precision value from the argument list */
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
precision = (int) va_arg(ap, int);
if (precision < 0) {
/* negative precision ignored */
/* Ignore negative precision */
precision = 0;
}
}
}
 
switch (fmt[i++]) {
/** @todo unimplemented qualifiers:
* t ptrdiff_t - ISO C 99
qualifier_t qualifier;
switch (uc) {
/** @todo Unimplemented qualifiers:
* t ptrdiff_t - ISO C 99
*/
case 'h': /* char or short */
case 'h':
/* Char or short */
qualifier = PrintfQualifierShort;
if (fmt[i] == 'h') {
i++;
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 'h') {
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
qualifier = PrintfQualifierByte;
}
break;
case 'l': /* long or long long*/
case 'l':
/* Long or long long */
qualifier = PrintfQualifierLong;
if (fmt[i] == 'l') {
i++;
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 'l') {
i = nxt;
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
qualifier = PrintfQualifierLongLong;
}
break;
case 'z': /* size_t */
qualifier = PrintfQualifierSizeT;
break;
default:
/* set default type */
/* Default type */
qualifier = PrintfQualifierInt;
--i;
}
}
base = 10;
 
switch (c = fmt[i]) {
 
unsigned int base = 10;
switch (uc) {
/*
* String and character conversions.
*/
case 's':
if ((retval = print_string(va_arg(ap, char*),
width, precision, flags, ps)) < 0) {
goto minus_out;
if (qualifier == PrintfQualifierLong)
retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps);
else
retval = print_str(va_arg(ap, char *), width, precision, flags, ps);
if (retval < 0) {
counter = -counter;
goto out;
}
counter += retval;
j = i + 1;
j = nxt;
goto next_char;
case 'c':
c = va_arg(ap, unsigned int);
retval = print_char(c, width, flags, ps);
if (qualifier == PrintfQualifierLong)
retval = print_wchar(va_arg(ap, wchar_t), width, flags, ps);
else
retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
if (retval < 0) {
goto minus_out;
}
 
counter = -counter;
goto out;
};
counter += retval;
j = i + 1;
j = nxt;
goto next_char;
 
/*
/*
* Integer values
*/
case 'P': /* pointer */
flags |= __PRINTF_FLAG_BIGCHARS;
case 'P':
/* Pointer */
flags |= __PRINTF_FLAG_BIGCHARS;
case 'p':
flags |= __PRINTF_FLAG_PREFIX;
base = 16;
qualifier = PrintfQualifierPointer;
break;
case 'b':
break;
case 'b':
base = 2;
break;
case 'o':
616,7 → 789,7
break;
case 'd':
case 'i':
flags |= __PRINTF_FLAG_SIGNED;
flags |= __PRINTF_FLAG_SIGNED;
case 'u':
break;
case 'X':
624,66 → 797,63
case 'x':
base = 16;
break;
/* percentile itself */
case '%':
/* Percentile itself */
case '%':
j = i;
goto next_char;
/*
* Bad formatting.
*/
default:
/*
* Unknown format. Now, j is the index of '%',
* so we will print the whole bad format
* sequence.
* Unknown format. Now, j is the index of '%'
* so we will print whole bad format sequence.
*/
goto next_char;
goto next_char;
}
/* Print integers */
size_t size;
uint64_t number;
switch (qualifier) {
case PrintfQualifierByte:
size = sizeof(unsigned char);
number = (uint64_t)va_arg(ap, unsigned int);
number = (uint64_t) va_arg(ap, unsigned int);
break;
case PrintfQualifierShort:
size = sizeof(unsigned short);
number = (uint64_t)va_arg(ap, unsigned int);
number = (uint64_t) va_arg(ap, unsigned int);
break;
case PrintfQualifierInt:
size = sizeof(unsigned int);
number = (uint64_t)va_arg(ap, unsigned int);
number = (uint64_t) va_arg(ap, unsigned int);
break;
case PrintfQualifierLong:
size = sizeof(unsigned long);
number = (uint64_t)va_arg(ap, unsigned long);
number = (uint64_t) va_arg(ap, unsigned long);
break;
case PrintfQualifierLongLong:
size = sizeof(unsigned long long);
number = (uint64_t)va_arg(ap,
unsigned long long);
number = (uint64_t) va_arg(ap, unsigned long long);
break;
case PrintfQualifierPointer:
size = sizeof(void *);
number = (uint64_t)(unsigned long)va_arg(ap,
void *);
number = (uint64_t) (unsigned long) va_arg(ap, void *);
break;
case PrintfQualifierSizeT:
size = sizeof(size_t);
number = (uint64_t)va_arg(ap, size_t);
break;
default: /* Unknown qualifier */
goto minus_out;
default:
/* Unknown qualifier */
counter = -counter;
goto out;
}
if (flags & __PRINTF_FLAG_SIGNED) {
if (number & (0x1 << (size * 8 - 1))) {
flags |= __PRINTF_FLAG_NEGATIVE;
if (size == sizeof(uint64_t)) {
number = -((int64_t)number);
number = -((int64_t) number);
} else {
number = ~number;
number &=
693,31 → 863,31
}
}
}
 
if ((retval = print_number(number, width, precision,
base, flags, ps)) < 0 ) {
goto minus_out;
base, flags, ps)) < 0) {
counter = -counter;
goto out;
}
 
counter += retval;
j = i + 1;
}
j = nxt;
}
next_char:
++i;
;
}
if (i > j) {
retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps);
if (retval < 0) { /* error */
goto minus_out;
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
/* Error */
counter = -counter;
goto out;
}
counter += retval;
}
return counter;
minus_out:
return -counter;
out:
return ((int) counter);
}
 
/** @}
/branches/tracing/uspace/lib/libc/generic/io/stream.c
42,79 → 42,45
#include <ipc/ns.h>
#include <ipc/fb.h>
#include <ipc/services.h>
#include <ipc/console.h>
#include <console.h>
#include <kbd/kbd.h>
#include <unistd.h>
#include <async.h>
#include <sys/types.h>
 
static int console_phone = -1;
 
ssize_t write_stderr(const void *buf, size_t count)
{
return count;
}
 
ssize_t read_stdin(void *buf, size_t count)
{
open_console();
if (console_phone >= 0) {
ipcarg_t r0, r1;
int cons_phone = console_open(false);
if (cons_phone >= 0) {
kbd_event_t ev;
int rc;
size_t i = 0;
while (i < count) {
if (async_req_0_2(console_phone, CONSOLE_GETCHAR, &r0, &r1) < 0)
return -1;
((char *) buf)[i++] = r0;
do {
rc = kbd_get_event(&ev);
if (rc < 0) return -1;
} while (ev.c == 0 || ev.type == KE_RELEASE);
((char *) buf)[i++] = ev.c;
}
return i;
} else {
} else
return -1;
}
}
 
ssize_t write_stdout(const void *buf, size_t count)
/** Write a string to klog. */
int klog_puts(const char *str)
{
open_console();
if (console_phone >= 0) {
int i;
for (i = 0; i < count; i++)
async_msg_1(console_phone, CONSOLE_PUTCHAR,
((const char *) buf)[i]);
return count;
} else
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count);
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) str, str_size(str));
}
 
void open_console(void)
{
if (console_phone < 0) {
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0, 0);
if (phone >= 0)
console_phone = phone;
}
}
 
void close_console(void)
{
if (console_phone >= 0) {
if (ipc_hangup(console_phone) == 0) {
console_phone = -1;
}
}
}
 
void klog_update(void)
{
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
int get_cons_phone(void)
{
open_console();
return console_phone;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/sysinfo.c
38,7 → 38,8
 
sysarg_t sysinfo_value(char *name)
{
return __SYSCALL2(SYS_SYSINFO_VALUE, (sysarg_t ) name, (sysarg_t) strlen(name));
return __SYSCALL2(SYS_SYSINFO_VALUE, (sysarg_t ) name,
(sysarg_t) str_size(name));
}
 
/** @}
/branches/tracing/uspace/lib/libc/Makefile
29,11 → 29,8
## Common compiler flags
#
 
include ../../Makefile.config
 
LIBC_PREFIX = $(shell pwd)
SOFTINT_PREFIX = ../softint
CONSOLE_PREFIX = ../../srv/console
 
## Setup toolchain
#
40,17 → 37,18
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I$(CONSOLE_PREFIX)
 
## Sources
#
 
 
GENERIC_SOURCES = \
generic/libc.c \
generic/ddi.c \
generic/as.c \
generic/cap.c \
generic/console.c \
generic/event.c \
generic/mem.c \
generic/string.c \
generic/fibril.c \
generic/pcb.c \
62,6 → 60,8
generic/io/asprintf.c \
generic/io/io.c \
generic/io/printf.c \
generic/io/fprintf.c \
generic/io/stdio.c \
generic/io/stream.c \
generic/io/sprintf.c \
generic/io/snprintf.c \
80,6 → 80,7
generic/time.c \
generic/err.c \
generic/stdlib.c \
generic/kbd.c \
generic/mman.c \
generic/udebug.c \
generic/vfs/vfs.c \
86,34 → 87,35
generic/vfs/canonify.c
 
ARCH_SOURCES += \
arch/$(ARCH)/src/entry.s \
arch/$(ARCH)/src/thread_entry.s
arch/$(UARCH)/src/entry.s \
arch/$(UARCH)/src/thread_entry.s
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS)
 
.PHONY: all clean depend kerninc
 
all: kerninc libc.a arch/$(ARCH)/_link.ld
all: kerninc libc.a arch/$(UARCH)/_link.ld
 
kerninc:
ln -sfn ../../../../kernel/generic/include include/kernel
ln -sfn kernel/arch include/arch
ln -sfn ../arch/$(ARCH)/include include/libarch
ln -sfn ../arch/$(UARCH)/include include/libarch
 
-include Makefile.depend
 
clean:
-rm -f include/kernel include/arch include/libarch libc.a arch/$(ARCH)/_link.ld Makefile.depend
find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \;
-rm -f include/kernel include/arch include/libarch libc.a arch/$(UARCH)/_link.ld Makefile.depend
find generic/ arch/$(UARCH)/ malloc -name '*.o' -follow -exec rm \{\} \;
 
depend: kerninc
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
 
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in
arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
 
%.o: %.S
/branches/tracing/uspace/lib/libc/arch/ppc64/include/syscall.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/atomic.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/regname.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/byteorder.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/stackarg.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/faddr.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/limits.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/tls.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/types.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/config.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/thread.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/include/fibril.h
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/Makefile.inc
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/src/entry.s
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/src/tls.c
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/src/fibril.S
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/src/thread_entry.s
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/src/syscall.c
File deleted
/branches/tracing/uspace/lib/libc/arch/ppc64/_link.ld.in
File deleted
/branches/tracing/uspace/lib/libc/arch/sparc64/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
31,13 → 31,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
.bss : {
*(.sbss);
*(COMMON);
/branches/tracing/uspace/lib/libc/arch/sparc64/include/ddi.h
0,0 → 1,92
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libsparc64
*/
 
#ifndef LIBC_sparc64_DDI_H_
#define LIBC_sparc64_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline memory_barrier(void)
{
asm volatile ("membar #LoadLoad | #StoreStore\n" ::: "memory");
}
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
memory_barrier();
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
memory_barrier();
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
memory_barrier();
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
uint8_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
uint16_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
uint32_t rv;
 
rv = *port;
memory_barrier();
 
return rv;
}
 
#endif
/branches/tracing/uspace/lib/libc/arch/sparc64/include/types.h
47,6 → 47,11
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
#endif
/branches/tracing/uspace/lib/libc/arch/sparc64/Makefile.inc
29,15 → 29,11
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = sparc64-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
ARCH_SOURCES += arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
CFLAGS += -mcpu=ultrasparc -m64
LFLAGS += -no-check-sections -N
/branches/tracing/uspace/lib/libc/arch/ia64/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
32,13 → 32,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
.bss : {
*(.sbss);
*(.scommon);
/branches/tracing/uspace/lib/libc/arch/ia64/include/ddi.h
1,5 → 1,5
/*
* Copyright (c) 2005 Jakub Jermar, Jakub Vana
* Copyright (c) 2005 Jakub Vana
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia64
/** @addtogroup libcia64
* @{
*/
/** @file
35,63 → 35,80
#ifndef LIBC_ia64_DDI_H_
#define LIBC_ia64_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
typedef uint64_t ioport_t;
#define IO_SPACE_BOUNDARY (64 * 1024)
 
uint64_t get_ia64_iospace_address(void);
 
extern uint64_t ia64_iospace_address;
 
#define IA64_IOSPACE_ADDRESS (ia64_iospace_address?ia64_iospace_address:(ia64_iospace_address=get_ia64_iospace_address()))
#define IA64_IOSPACE_ADDRESS \
(ia64_iospace_address ? \
ia64_iospace_address : \
(ia64_iospace_address = get_ia64_iospace_address()))
 
static inline void outb(ioport_t port,uint8_t v)
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((ioport8_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outw(ioport_t port,uint16_t v)
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((ioport16_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline void outl(ioport_t port,uint32_t v)
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v;
uintptr_t prt = (uintptr_t) port;
 
*((ioport32_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
 
asm volatile ("mf\n" ::: "memory");
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
 
static inline uint8_t inb(ioport_t port)
{
asm volatile ("mf\n" ::: "memory");
 
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
return *((ioport8_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint16_t inw(ioport_t port)
static inline uint16_t pio_read_16(ioport16_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 ))));
return *((ioport16_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
static inline uint32_t inl(ioport_t port)
static inline uint32_t pio_read_32(ioport32_t *port)
{
uintptr_t prt = (uintptr_t) port;
 
asm volatile ("mf\n" ::: "memory");
 
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 ))));
return *((ioport32_t *)(IA64_IOSPACE_ADDRESS +
((prt & 0xfff) | ((prt >> 2) << 12))));
}
 
 
 
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/arch/ia64/include/types.h
47,6 → 47,11
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
typedef unsigned char __r8; /* Reserve byte */
/branches/tracing/uspace/lib/libc/arch/ia64/Makefile.inc
29,10 → 29,6
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
39,10 → 35,10
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c\
arch/$(ARCH)/src/ddi.c
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/ddi.c
 
BFD_NAME = elf64-ia64-little
BFD_ARCH = ia64-elf64
/branches/tracing/uspace/lib/libc/arch/ia64/src/entry.s
38,7 → 38,7
#
__entry:
alloc loc0 = ar.pfs, 0, 1, 2, 0
mov r1 = _gp
movl r1 = _gp
 
# Pass PCB pointer as the first argument to __main
mov out0 = r2
/branches/tracing/uspace/lib/libc/arch/ia64/src/thread_entry.s
36,7 → 36,7
__thread_entry:
alloc loc0 = ar.pfs, 0, 1, 1, 0
 
mov r1 = _gp
movl r1 = _gp
#
# r8 contains address of uarg structure.
/branches/tracing/uspace/lib/libc/arch/arm32/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
28,13 → 28,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
.bss : {
*(.sbss);
*(.scommon);
/branches/tracing/uspace/lib/libc/arch/arm32/include/ddi.h
0,0 → 1,69
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libcarm32
*/
 
#ifndef LIBC_arm32_DDI_H_
#define LIBC_arm32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
/branches/tracing/uspace/lib/libc/arch/arm32/include/types.h
48,6 → 48,11
typedef unsigned long int uint32_t;
typedef unsigned long long int uint64_t;
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
#endif
/branches/tracing/uspace/lib/libc/arch/arm32/Makefile.inc
30,20 → 30,16
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
AFLAGS +=
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c \
arch/$(ARCH)/src/eabi.S
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/eabi.S
 
BFD_NAME = elf32-littlearm
BFD_ARCH = arm
/branches/tracing/uspace/lib/libc/arch/mips32eb/include/ddi.h
0,0 → 1,0
link ../../mips32/include/ddi.h
/branches/tracing/uspace/lib/libc/arch/mips32eb/Makefile.inc
29,19 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mips-sgi-irix5
TARGET = mips-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
CFLAGS += -mips3
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
LFLAGS += -N
 
BFD_ARCH = mips
BFD_NAME = elf32-big
BFD_NAME = elf32-tradbigmips
/branches/tracing/uspace/lib/libc/arch/ppc32/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
27,13 → 27,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
.bss : {
*(.sbss);
*(COMMON);
/branches/tracing/uspace/lib/libc/arch/ppc32/include/ddi.h
0,0 → 1,69
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libcppc32
*/
 
#ifndef LIBC_ppc32_DDI_H_
#define LIBC_ppc32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
/branches/tracing/uspace/lib/libc/arch/ppc32/include/types.h
47,6 → 47,11
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
#endif
/branches/tracing/uspace/lib/libc/arch/ppc32/Makefile.inc
29,16 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ppc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
CFLAGS += -mcpu=powerpc -msoft-float -m32
AFLAGS += -a32
/branches/tracing/uspace/lib/libc/arch/amd64/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
26,13 → 26,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
.bss : {
*(COMMON);
*(.bss);
/branches/tracing/uspace/lib/libc/arch/amd64/include/types.h
47,6 → 47,11
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
 
typedef int64_t ssize_t;
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
 
#endif
/branches/tracing/uspace/lib/libc/arch/amd64/Makefile.inc
29,16 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = amd64-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
LFLAGS += -N
 
/branches/tracing/uspace/lib/libc/arch/mips32/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
33,13 → 33,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
 
.sbss : {
*(.scommon);
/branches/tracing/uspace/lib/libc/arch/mips32/include/atomic.h
59,13 → 59,14
asm volatile (
"1:\n"
" ll %0, %1\n"
" addiu %0, %0, %3\n" /* same as addi, but never traps on overflow */
" addu %0, %0, %3\n" /* same as add, but never traps on overflow */
" move %2, %0\n"
" sc %0, %1\n"
" beq %0, %4, 1b\n" /* if the atomic operation failed, try again */
/* nop */ /* nop is inserted automatically by compiler */
" nop\n"
: "=&r" (tmp), "+m" (val->count), "=&r" (v)
: "i" (i), "i" (0)
: "r" (i), "i" (0)
);
 
return v;
/branches/tracing/uspace/lib/libc/arch/mips32/include/ddi.h
0,0 → 1,69
/*
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @file
* @ingroup libcmips32
*/
 
#ifndef LIBC_mips32_DDI_H_
#define LIBC_mips32_DDI_H_
 
#include <sys/types.h>
#include <libarch/types.h>
 
static inline void pio_write_8(ioport8_t *port, uint8_t v)
{
*port = v;
}
 
static inline void pio_write_16(ioport16_t *port, uint16_t v)
{
*port = v;
}
 
static inline void pio_write_32(ioport32_t *port, uint32_t v)
{
*port = v;
}
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
return *port;
}
 
static inline uint16_t pio_read_16(ioport16_t *port)
{
return *port;
}
 
static inline uint32_t pio_read_32(ioport32_t *port)
{
return *port;
}
 
#endif
/branches/tracing/uspace/lib/libc/arch/mips32/include/types.h
48,6 → 48,11
typedef unsigned long int uint32_t;
typedef unsigned long long int uint64_t;
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
#endif
/branches/tracing/uspace/lib/libc/arch/mips32/Makefile.inc
29,23 → 29,13
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
CFLAGS += -mips3
 
-include ../../Makefile.config
ifeq ($(CONFIG_MIPS_FPU),y)
CFLAGS += -DCONFIG_MIPS_FPU
endif
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
 
 
BFD_ARCH = mips
BFD_NAME = elf32-tradlittlemips
/branches/tracing/uspace/lib/libc/arch/ia32/_link.ld.in
1,4 → 1,4
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
26,13 → 26,11
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
_tls_alignment = ALIGNOF(.tdata);
.bss : {
*(COMMON);
*(.bss);
/branches/tracing/uspace/lib/libc/arch/ia32/include/ddi.h
33,43 → 33,72
#ifndef LIBC_ia32_DDI_H_
#define LIBC_ia32_DDI_H_
 
static inline void outb(int16_t port, uint8_t b)
#include <sys/types.h>
#include <libarch/types.h>
 
#define IO_SPACE_BOUNDARY ((void *) (64 * 1024))
 
static inline uint8_t pio_read_8(ioport8_t *port)
{
asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port));
uint8_t val;
asm volatile (
"inb %w[port], %b[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
static inline void outw(int16_t port, int16_t w)
static inline uint16_t pio_read_16(ioport16_t *port)
{
asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port));
uint16_t val;
asm volatile (
"inw %w[port], %w[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
static inline void outl(int16_t port, uint32_t l)
static inline uint32_t pio_read_32(ioport32_t *port)
{
asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port));
uint32_t val;
asm volatile (
"inl %w[port], %[val]\n"
: [val] "=a" (val)
: [port] "d" (port)
);
return val;
}
 
static inline uint8_t inb(int16_t port)
static inline void pio_write_8(ioport8_t *port, uint8_t val)
{
uint8_t val;
 
asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port));
return val;
asm volatile (
"outb %b[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
static inline int16_t inw(int16_t port)
static inline void pio_write_16(ioport16_t *port, uint16_t val)
{
int16_t val;
 
asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port));
return val;
asm volatile (
"outw %w[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
static inline uint32_t inl(int16_t port)
static inline void pio_write_32(ioport32_t *port, uint32_t val)
{
uint32_t val;
 
asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port));
return val;
asm volatile (
"outl %[val], %w[port]\n"
:: [val] "a" (val), [port] "d" (port)
);
}
 
#endif
/branches/tracing/uspace/lib/libc/arch/ia32/include/types.h
47,6 → 47,11
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
 
typedef int32_t ssize_t;
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
 
#endif
/branches/tracing/uspace/lib/libc/arch/ia32/Makefile.inc
29,17 → 29,13
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c \
arch/$(ARCH)/src/setjmp.S
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/setjmp.S
 
LFLAGS += -N