/branches/network/uspace/lib/libc/include/console.h |
---|
40,17 → 40,15 |
#include <sys/types.h> |
#include <bool.h> |
extern void console_open(bool); |
extern int console_open(bool); |
extern void console_close(void); |
extern int console_phone_get(bool); |
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 *buf, size_t nbyte); |
extern void console_putstr(const char *s); |
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 *); |
/branches/network/uspace/lib/libc/include/string.h |
---|
45,8 → 45,8 |
/**< No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
/**< Maximum size of a string containing cnt characters */ |
#define STR_BOUNDS(cnt) (cnt << 2) |
/**< Maximum size of a string containing @c length characters */ |
#define STR_BOUNDS(length) ((length) << 2) |
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); |
69,34 → 69,26 |
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_ncpy(char *dst, const char *src, size_t size); |
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 strcmp(const char *, const char *); |
extern int strncmp(const char *, const char *, size_t); |
extern int stricmp(const char *, const char *); |
extern char *strcpy(char *, const char *); |
extern char *strncpy(char *, const char *, size_t); |
extern char *strcat(char *, const char *); |
extern size_t strlen(const char *); |
extern char *strdup(const char *); |
extern char *strchr(const char *, int); |
extern char *strrchr(const char *, int); |
extern long int strtol(const char *, char **, int); |
extern unsigned long strtoul(const char *, char **, int); |
/branches/network/uspace/lib/libc/include/vfs/vfs.h |
---|
39,7 → 39,7 |
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/network/uspace/lib/libc/include/async.h |
---|
98,22 → 98,22 |
/* 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 |
253,8 → 253,6 |
fibril_dec_sercount(); |
} |
extern bool in_interrupt_handler(void); |
extern atomic_t async_futex; |
#endif |
/branches/network/uspace/lib/libc/include/stdio.h |
---|
49,7 → 49,7 |
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 { |
/branches/network/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/network/uspace/lib/libc/include/io/stream.h |
---|
39,13 → 39,9 |
#define EMFILE -17 |
extern ssize_t read_stdin(void *, size_t); |
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 flush_stdout(void); |
#endif |
/** @} |
/branches/network/uspace/lib/libc/include/ipc/fb.h |
---|
66,7 → 66,9 |
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/network/uspace/lib/libc/generic/kbd.c |
---|
42,7 → 42,7 |
int kbd_get_event(kbd_event_t *ev) |
{ |
int cons_phone = console_phone_get(true); |
int cons_phone = console_open(true); |
ipcarg_t r0, r1, r2, r3; |
int rc; |
/branches/network/uspace/lib/libc/generic/console.c |
---|
34,6 → 34,7 |
/** @file |
*/ |
#include <libc.h> |
#include <async.h> |
#include <io/stream.h> |
#include <ipc/console.h> |
56,86 → 57,50 |
/** Pointer to first available field in cbuffer. */ |
static char *cbp = cbuffer; |
static ssize_t cons_write(const char *buf, size_t nbyte); |
static void cons_putchar(wchar_t c); |
static void cbuffer_flush(void); |
static void cbuffer_drain(void); |
static inline void cbuffer_putc(int c); |
void console_open(bool blocking) |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
{ |
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); |
console_wait(); |
async_msg_1(console_phone, CONSOLE_PUTCHAR, c); |
} |
if (phone >= 0) |
console_phone = phone; |
} |
} |
void console_close(void) |
/** 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) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
} |
} |
} |
async_serialize_start(); |
int console_phone_get(bool blocking) |
{ |
if (console_phone < 0) |
console_open(blocking); |
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); |
return console_phone; |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
} |
void console_wait(void) |
{ |
while (console_phone < 0) |
console_open(true); |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_drain(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); |
} |
void console_goto(int row, int col) |
{ |
int cons_phone = console_phone_get(true); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_GOTO, row, col); |
} |
void console_putchar(wchar_t c) |
{ |
// cbuffer_putc(c); |
cbuffer_flush(); |
cons_putchar(c); |
} |
/** Write all data from output buffer to the console. */ |
static void cbuffer_flush(void) |
{ |
int rc; |
int len; |
size_t len = cbp - cbuffer; |
len = cbp - cbuffer; |
while (len > 0) { |
rc = cons_write(cbuffer, cbp - cbuffer); |
ssize_t rc = cons_write(cbuffer, cbp - cbuffer); |
if (rc < 0) |
return; |
152,7 → 117,7 |
} |
/** Write one character to the output buffer. */ |
static inline void cbuffer_putc(int c) |
static inline void cbuffer_putc(char c) |
{ |
if (cbp == cbuffer_end) |
cbuffer_flush(); |
163,88 → 128,53 |
cbuffer_flush(); |
} |
/** Write one character to the console via IPC. */ |
static void cons_putchar(wchar_t c) |
int console_open(bool blocking) |
{ |
int cons_phone = console_phone_get(true); |
async_msg_1(cons_phone, CONSOLE_PUTCHAR, c); |
} |
if (console_phone < 0) { |
int phone; |
/** Write characters to the console via IPC. */ |
static ssize_t cons_write(const char *buf, size_t nbyte) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
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); |
async_serialize_start(); |
req = async_send_0(cons_phone, CONSOLE_WRITE, &answer); |
rc = ipc_data_write_start(cons_phone, (void *) buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
return (ssize_t) rc; |
if (phone >= 0) |
console_phone = phone; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
return console_phone; |
} |
/** Write characters to the console. */ |
ssize_t console_write(const char *buf, size_t nbyte) |
void console_close(void) |
{ |
size_t left; |
left = nbyte; |
while (left > 0) { |
cbuffer_putc(*buf++); |
--left; |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) |
console_phone = -1; |
} |
return nbyte; |
} |
/** Write a NULL-terminated string to the console. */ |
void console_putstr(const char *s) |
void console_wait(void) |
{ |
size_t len; |
ssize_t rc; |
len = strlen(s); |
while (len > 0) { |
rc = console_write(s, len); |
if (rc < 0) |
return; /* Error */ |
s += rc; |
len -= rc; |
while (console_phone < 0) |
console_open(true); |
} |
} |
/** Flush all output to the console. */ |
void console_flush(void) |
void console_clear(void) |
{ |
int cons_phone = console_phone_get(false); |
cbuffer_flush(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
console_wait(); |
cbuffer_drain(); |
async_msg_0(console_phone, CONSOLE_CLEAR); |
} |
int console_get_size(int *rows, int *cols) |
{ |
int cons_phone = console_phone_get(true); |
ipcarg_t r, c; |
int rc; |
console_wait(); |
rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c); |
ipcarg_t r; |
ipcarg_t c; |
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c); |
*rows = (int) r; |
*cols = (int) c; |
254,43 → 184,91 |
void console_set_style(int style) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
async_msg_1(console_phone, CONSOLE_SET_STYLE, style); |
} |
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
void console_cursor_visibility(int show) |
{ |
int cons_phone = console_phone_get(true); |
console_wait(); |
cbuffer_flush(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
void console_kcon_enable(void) |
{ |
int cons_phone = console_phone_get(true); |
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_0(cons_phone, CONSOLE_KCON_ENABLE); |
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/network/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/network/uspace/lib/libc/generic/string.c |
---|
35,11 → 35,13 |
#include <string.h> |
#include <stdlib.h> |
#include <assert.h> |
#include <limits.h> |
#include <ctype.h> |
#include <malloc.h> |
#include <errno.h> |
#include <align.h> |
#include <mem.h> |
#include <string.h> |
/** Byte mask consisting of lowest @n bits (out of 8) */ |
461,40 → 463,91 |
} |
/** Copy NULL-terminated string. |
/** Copy string. |
* |
* Copy source 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). |
* 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) |
{ |
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, 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. |
* |
* @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 *dst, const char *src, size_t size) |
void str_ncpy(char *dest, size_t size, const char *src, size_t n) |
{ |
/* No space for the NULL-terminator in the buffer */ |
if (size == 0) |
return; |
wchar_t ch; |
size_t str_off = 0; |
size_t dst_off = 0; |
size_t src_off; |
size_t dest_off; |
while ((ch = str_decode(src, &str_off, STR_NO_LIMIT)) != 0) { |
if (chr_encode(ch, dst, &dst_off, size) != EOK) |
/* 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; |
} |
if (dst_off >= size) |
dst[size - 1] = 0; |
else |
dst[dst_off] = 0; |
dest[dest_off] = '\0'; |
} |
/** 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) |
{ |
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. |
535,21 → 588,45 |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a str or NULL if not found. |
* |
*/ |
const char *str_chr(const char *str, wchar_t ch) |
{ |
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 + off); |
return (str + last); |
last = off; |
} |
return NULL; |
} |
/** Find last occurence of character in string. |
* |
* @param str String to search. |
* @param ch Character to look for. |
* |
* @return Pointer to character in @a str or NULL if not found. |
*/ |
const char *str_rchr(const char *str, wchar_t ch) |
{ |
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; |
} |
/** Insert a wide character into a wide string. |
* |
* Insert a wide character into a wide string at position |
606,42 → 683,6 |
return true; |
} |
/** Count the number of characters in the string, not including terminating 0. |
* |
* @param str String. |
* @return Number of characters in string. |
*/ |
size_t strlen(const char *str) |
{ |
size_t counter = 0; |
while (str[counter] != 0) |
counter++; |
return counter; |
} |
int strcmp(const char *a, const char *b) |
{ |
int c = 0; |
while (a[c] && b[c] && (!(a[c] - b[c]))) |
c++; |
return (a[c] - b[c]); |
} |
int strncmp(const char *a, const char *b, size_t n) |
{ |
size_t c = 0; |
while (c < n && a[c] && b[c] && (!(a[c] - b[c]))) |
c++; |
return ( c < n ? a[c] - b[c] : 0); |
} |
int stricmp(const char *a, const char *b) |
{ |
int c = 0; |
652,44 → 693,6 |
return (tolower(a[c]) - tolower(b[c])); |
} |
/** Return pointer to the first occurence of character c 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. |
*/ |
char *strchr(const char *str, int c) |
{ |
while (*str != '\0') { |
if (*str == (char) c) |
return (char *) str; |
str++; |
} |
return NULL; |
} |
/** Return pointer to the last occurence of character c 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. |
*/ |
char *strrchr(const char *str, int c) |
{ |
char *retval = NULL; |
while (*str != '\0') { |
if (*str == (char) c) |
retval = (char *) str; |
str++; |
} |
return (char *) retval; |
} |
/** Convert string to a number. |
* Core of strtol and strtoul functions. |
* |
839,44 → 842,15 |
return (sgn ? -number : number); |
} |
char *strcpy(char *dest, const char *src) |
char *str_dup(const char *src) |
{ |
char *orig = dest; |
size_t size = str_size(src); |
void *dest = malloc(size + 1); |
while ((*(dest++) = *(src++))) |
; |
return orig; |
} |
char *strncpy(char *dest, const char *src, size_t n) |
{ |
char *orig = dest; |
while ((*(dest++) = *(src++)) && --n) |
; |
return orig; |
} |
char *strcat(char *dest, const char *src) |
{ |
char *orig = dest; |
while (*dest++) |
; |
--dest; |
while ((*dest++ = *src++)) |
; |
return orig; |
} |
char * strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) |
if (dest == NULL) |
return (char *) NULL; |
return (char *) memcpy(ret, s1, len); |
return (char *) memcpy(dest, src, size + 1); |
} |
char *strtok(char *s, const char *delim) |
894,11 → 868,11 |
s = *next; |
/* Skip over leading delimiters. */ |
while (*s && (strchr(delim, *s) != NULL)) ++s; |
while (*s && (str_chr(delim, *s) != NULL)) ++s; |
start = s; |
/* Skip over token characters. */ |
while (*s && (strchr(delim, *s) == NULL)) ++s; |
while (*s && (str_chr(delim, *s) == NULL)) ++s; |
end = s; |
*next = (*s ? s + 1 : s); |
/branches/network/uspace/lib/libc/generic/loader.c |
---|
180,7 → 180,7 |
dp = arg_buf; |
while (*ap != NULL) { |
str_ncpy(dp, *ap, buffer_size - (dp - arg_buf)); |
str_cpy(dp, buffer_size - (dp - arg_buf), *ap); |
dp += str_size(*ap) + 1; |
++ap; |
/branches/network/uspace/lib/libc/generic/thread.c |
---|
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/network/uspace/lib/libc/generic/libc.c |
---|
48,6 → 48,7 |
#include <ipc/ipc.h> |
#include <async.h> |
#include <as.h> |
#include <console.h> |
#include <loader/pcb.h> |
extern char _heap; |
83,6 → 84,7 |
} |
main(argc, argv); |
console_flush(); |
} |
void __exit(void) |
/branches/network/uspace/lib/libc/generic/async.c |
---|
35,14 → 35,15 |
/** |
* 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 |
* - async_send_*(): Send asynchronously. If the kernel refuses to send |
* more messages, [ try to get responses from kernel, if |
* nothing found, might try synchronous ] |
* |
66,12 → 67,12 |
* |
* |
* 2) Multithreaded server application |
* |
* main() |
* { |
* async_manager(); |
* } |
* |
* |
* my_client_connection(icallid, *icall) |
* { |
* if (want_refuse) { |
85,7 → 86,7 |
* ipc_answer_2(callid, 1, 2, 3); |
* |
* callid = async_get_call(&call); |
* .... |
* ... |
* } |
* |
*/ |
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; |
/** 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,7 → 131,8 |
awaiter_t wdata; |
/** If reply was received. */ |
int done; |
bool done; |
/** Pointer to where the answer data is stored. */ |
ipc_call_t *dataptr; |
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,17 → 190,11 |
*/ |
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; |
} |
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. |
209,11 → 202,12 |
* @param key Pointer to source phone hash. |
* |
* @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. |
223,14 → 217,12 |
* @param item Connection hash table item. |
* |
* @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. |
239,6 → 231,7 |
* hash table. |
* |
* @param item Connection hash table item being removed. |
* |
*/ |
static void conn_remove(link_t *item) |
{ |
256,22 → 249,23 |
/** Sort in current fibril's timeout request. |
* |
* @param wd Wait data of the current fibril. |
* |
*/ |
static void insert_timeout(awaiter_t *wd) |
{ |
link_t *tmp; |
awaiter_t *cur; |
wd->timedout = false; |
wd->inlist = true; |
wd->timedout = 0; |
wd->inlist = 1; |
link_t *tmp = timeout_list.next; |
while (tmp != &timeout_list) { |
awaiter_t *cur = list_get_instance(tmp, awaiter_t, link); |
tmp = timeout_list.next; |
while (tmp != &timeout_list) { |
cur = list_get_instance(tmp, awaiter_t, link); |
if (tv_gteq(&cur->expires, &wd->expires)) |
break; |
tmp = tmp->next; |
} |
list_append(&wd->link, tmp); |
} |
284,28 → 278,30 |
* @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); |
315,20 → 311,71 |
/* 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. |
339,20 → 386,19 |
* 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 *($&$(*&$ |
* a compiler. |
*/ |
conn = FIBRIL_connection; |
connection_t *conn = FIBRIL_connection; |
futex_down(&async_futex); |
359,15 → 405,16 |
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); |
404,6 → 453,7 |
* |
* @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. |
* |
* 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) |
{ |
427,14 → 480,14 |
* @param arg Connection structure pointer. |
* |
* @return Always zero. |
* |
*/ |
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,7 → 516,7 |
/** 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. |
* |
477,29 → 530,31 |
* connection. |
* |
* @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); |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
if (!conn->wdata.fid) { |
free(conn); |
if (callid) |
508,7 → 563,8 |
} |
/* 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); |
531,9 → 587,7 |
{ |
/* 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; |
} |
557,27 → 611,29 |
static void handle_expired_timeouts(void) |
{ |
struct timeval tv; |
awaiter_t *waiter; |
link_t *cur; |
gettimeofday(&tv, NULL); |
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. |
*/ |
if (!waiter->active) { |
waiter->active = 1; |
waiter->active = true; |
fibril_add_ready(waiter->fid); |
} |
} |
588,16 → 644,11 |
/** Endless loop dispatching incoming calls and answers. |
* |
* @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); |
/* |
606,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(); |
619,9 → 676,12 |
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(); |
628,9 → 688,8 |
continue; |
} |
if (callid & IPC_CALLID_ANSWERED) { |
if (callid & IPC_CALLID_ANSWERED) |
continue; |
} |
handle_call(callid, &call); |
} |
643,12 → 702,13 |
* When more kernel threads are used, one async manager should exist per thread. |
* |
* @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 |
*/ |
660,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); |
} |
694,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 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; |
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); |
} |
735,22 → 796,25 |
* @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; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
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, !_in_interrupt_handler); |
reply_received, true); |
return (aid_t) msg; |
} |
770,23 → 834,26 |
* @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; |
amsg_t *msg = malloc(sizeof(*msg)); |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
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, !_in_interrupt_handler); |
reply_received, true); |
return (aid_t) msg; |
} |
796,6 → 863,7 |
* @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) |
{ |
808,14 → 876,18 |
} |
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); |
} |
827,6 → 899,7 |
* @param timeout Timeout in microseconds. |
* |
* @return Zero on success, ETIMEOUT if the timeout has expired. |
* |
*/ |
int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, suseconds_t timeout) |
{ |
846,13 → 919,14 |
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; |
859,6 → 933,7 |
done: |
if (retval) |
*retval = msg->retval; |
free(msg); |
return 0; |
869,26 → 944,30 |
* The current fibril is suspended but the thread continues to execute. |
* |
* @param timeout Duration of the wait in microseconds. |
* |
*/ |
void async_usleep(suseconds_t timeout) |
{ |
amsg_t *msg; |
amsg_t *msg = malloc(sizeof(*msg)); |
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); |
} |
895,6 → 974,7 |
/** Setter for client_connection function pointer. |
* |
* @param conn Function that will implement a new connection fibril. |
* |
*/ |
void async_set_client_connection(async_client_conn_t conn) |
{ |
903,12 → 983,12 |
/** Setter for interrupt_received function pointer. |
* |
* @param conn Function that will implement a new interrupt |
* @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. |
929,7 → 1009,9 |
* @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, |
936,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) |
*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; |
} |
970,7 → 1058,9 |
* @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, |
977,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) |
*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/network/uspace/lib/libc/generic/vfs/vfs.c |
---|
76,7 → 76,7 |
futex_up(&cwd_futex); |
return NULL; |
} |
str_ncpy(ncwd_path_nc, cwd_path, cwd_size + 1 + size + 1); |
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 { |
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); |
155,7 → 155,7 |
} |
int mount(const char *fs_name, const char *mp, const char *dev, |
const unsigned int flags) |
const char *opts, const unsigned int flags) |
{ |
int res; |
ipcarg_t rc; |
185,6 → 185,15 |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
194,6 → 203,16 |
return (int) rc; |
} |
/* 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(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
534,7 → 553,7 |
futex_up(&cwd_futex); |
return NULL; |
} |
str_ncpy(buf, cwd_path, size); |
str_cpy(buf, size, cwd_path); |
futex_up(&cwd_futex); |
return buf; |
} |
/branches/network/uspace/lib/libc/generic/io/io.c |
---|
38,6 → 38,7 |
#include <io/io.h> |
#include <string.h> |
#include <errno.h> |
#include <console.h> |
const static char nl = '\n'; |
49,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; |
} |
64,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; |
81,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; |
96,7 → 98,7 |
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK) |
return EOF; |
if (write_stdout((void *) buf, offs) == offs) |
if (console_write((void *) buf, offs) == offs) |
return c; |
return EOF; |
106,7 → 108,7 |
{ |
unsigned char c; |
flush_stdout(); |
console_flush(); |
if (read_stdin((void *) &c, 1) == 1) |
return c; |
115,8 → 117,10 |
int fflush(FILE *f) |
{ |
/* Dummy implementation */ |
(void) f; |
return flush_stdout(); |
console_flush(); |
return 0; |
} |
/** @} |
/branches/network/uspace/lib/libc/generic/io/vprintf.c |
---|
38,6 → 38,7 |
#include <io/printf_core.h> |
#include <futex.h> |
#include <async.h> |
#include <console.h> |
static atomic_t printf_futex = FUTEX_INITIALIZER; |
50,7 → 51,7 |
while (offset < size) { |
prev = offset; |
str_decode(str, &offset, size); |
write_stdout(str + prev, offset - prev); |
console_write(str + prev, offset - prev); |
chars++; |
} |
67,7 → 68,7 |
while (offset < size) { |
boff = 0; |
chr_encode(str[chars], buf, &boff, 4); |
write_stdout(buf, boff); |
console_write(buf, boff); |
chars++; |
offset += sizeof(wchar_t); |
} |
/branches/network/uspace/lib/libc/generic/io/stream.c |
---|
49,14 → 49,9 |
#include <async.h> |
#include <sys/types.h> |
ssize_t write_stderr(const void *buf, size_t count) |
{ |
return count; |
} |
ssize_t read_stdin(void *buf, size_t count) |
{ |
int cons_phone = console_phone_get(false); |
int cons_phone = console_open(false); |
if (cons_phone >= 0) { |
kbd_event_t ev; |
72,39 → 67,10 |
((char *) buf)[i++] = ev.c; |
} |
return i; |
} else { |
} else |
return -1; |
} |
} |
ssize_t write_stdout(const void *buf, size_t count) |
{ |
int cons_phone = console_phone_get(false); |
int left, rc; |
if (cons_phone >= 0) { |
int i; |
left = count; |
while (left > 0) { |
rc = console_write(buf, left); |
if (rc < 0) |
break; |
buf += rc; |
left -= rc; |
} |
return count; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
} |
int flush_stdout(void) |
{ |
console_flush(); |
return 0; |
} |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
/branches/network/uspace/lib/libc/arch/ia64/include/ddi.h |
---|
53,7 → 53,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
63,7 → 63,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
73,7 → 73,7 |
{ |
uintptr_t prt = (uintptr_t) port; |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + |
*((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))) = v; |
asm volatile ("mf\n" ::: "memory"); |
85,7 → 85,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport8_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
95,7 → 95,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport16_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |
105,7 → 105,7 |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + |
return *((ioport32_t *)(IA64_IOSPACE_ADDRESS + |
((prt & 0xfff) | ((prt >> 2) << 12)))); |
} |