Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4581 → Rev 4718

/branches/network/uspace/lib/libc/generic/task.c
148,10 → 148,23
return 0;
}
 
int task_wait(task_id_t id)
int task_wait(task_id_t id, task_exit_t *texit, int *retval)
{
return (int) async_req_2_0(PHONE_NS, NS_TASK_WAIT, LOWER32(id), UPPER32(id));
ipcarg_t te, rv;
int rc;
 
rc = (int) async_req_2_2(PHONE_NS, NS_TASK_WAIT, LOWER32(id),
UPPER32(id), &te, &rv);
*texit = te;
*retval = rv;
 
return rc;
}
 
int task_retval(int val)
{
return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val);
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/getopt.c
47,7 → 47,7
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
const char *optarg; /* argument associated with option */
 
 
#define IGNORE_FIRST (*options == '-' || *options == '+')
162,7 → 162,7
char **nargv;
const char *options;
{
char *oli; /* option letter list index */
const char *oli; /* option letter list index */
int optchar;
 
assert(nargv != NULL);
275,7 → 275,7
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = *place;
optarg = place;
/* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
353,7 → 353,8
 
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
char *current_argv, *has_equal;
char *current_argv;
const char *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
 
/branches/network/uspace/lib/libc/generic/as.c
38,23 → 38,23
#include <align.h>
#include <sys/types.h>
#include <bitops.h>
#include <malloc.h>
 
/**
* Either 4*256M on 32-bit architecures or 16*256M on 64-bit architectures.
*/
#define MAX_HEAP_SIZE (sizeof(uintptr_t)<<28)
/** Last position allocated by as_get_mappable_page */
static uintptr_t last_allocated = 0;
 
/** Create address space area.
*
* @param address Virtual address where to place new address space area.
* @param size Size of the area.
* @param flags Flags describing type of the area.
* @param size Size of the area.
* @param flags Flags describing type of the area.
*
* @return address on success, (void *) -1 otherwise.
*
*/
void *as_area_create(void *address, size_t size, int flags)
{
return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t ) address,
return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t) address,
(sysarg_t) size, (sysarg_t) flags);
}
 
61,15 → 61,16
/** Resize address space area.
*
* @param address Virtual address pointing into already existing address space
* area.
* @param size New requested size of the area.
* @param flags Currently unused.
* area.
* @param size New requested size of the area.
* @param flags Currently unused.
*
* @return Zero on success or a code from @ref errno.h on failure.
* @return zero on success or a code from @ref errno.h on failure.
*
*/
int as_area_resize(void *address, size_t size, int flags)
{
return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t ) address,
return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t) address,
(sysarg_t) size, (sysarg_t) flags);
}
 
76,22 → 77,24
/** Destroy address space area.
*
* @param address Virtual address pointing into the address space area being
* destroyed.
* destroyed.
*
* @return Zero on success or a code from @ref errno.h on failure.
* @return zero on success or a code from @ref errno.h on failure.
*
*/
int as_area_destroy(void *address)
{
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address);
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t) address);
}
 
/** Change address-space area flags.
*
* @param address Virtual address pointing into the address space area being
* modified.
* @param flags New flags describing type of the area.
* modified.
* @param flags New flags describing type of the area.
*
* @return Zero on success or a code from @ref errno.h on failure.
* @return zero on success or a code from @ref errno.h on failure.
*
*/
int as_area_change_flags(void *address, int flags)
{
99,101 → 102,29
(sysarg_t) flags);
}
 
static size_t heapsize = 0;
static size_t maxheapsize = (size_t) (-1);
 
static void *last_allocated = 0;
 
/* Start of heap linker symbol */
extern char _heap;
 
/** Sbrk emulation
*
* @param incr New area that should be allocated or negative,
if it should be shrinked
* @return Pointer to newly allocated area
*/
void *sbrk(ssize_t incr)
{
int rc;
void *res;
/* Check for invalid values */
if ((incr < 0) && (((size_t) -incr) > heapsize))
return NULL;
/* Check for too large value */
if ((incr > 0) && (incr + heapsize < heapsize))
return NULL;
/* Check for too small values */
if ((incr < 0) && (incr + heapsize > heapsize))
return NULL;
/* Check for user limit */
if ((maxheapsize != (size_t) (-1)) && (heapsize + incr) > maxheapsize)
return NULL;
rc = as_area_resize(&_heap, heapsize + incr, 0);
if (rc != 0)
return NULL;
/* Compute start of new area */
res = (void *) &_heap + heapsize;
 
heapsize += incr;
 
return res;
}
 
/** Set maximum heap size and return pointer just after the heap */
void *set_maxheapsize(size_t mhs)
{
maxheapsize = mhs;
/* Return pointer to area not managed by sbrk */
return ((void *) &_heap + maxheapsize);
}
 
/** Return pointer to some unmapped area, where fits new as_area
*
* @param sz Requested size of the allocation.
* @param size Requested size of the allocation.
*
* @return Pointer to the beginning
* @return pointer to the beginning
*
* TODO: make some first_fit/... algorithm, we are now just incrementing
* the pointer to last area
*/
void *as_get_mappable_page(size_t sz)
void *as_get_mappable_page(size_t size)
{
void *res;
uint64_t asz;
int i;
if (size == 0)
return NULL;
if (!sz)
return NULL;
 
asz = 1 << (fnzb64(sz - 1) + 1);
 
/* Set heapsize to some meaningful value */
if (maxheapsize == (size_t) -1)
set_maxheapsize(MAX_HEAP_SIZE);
size_t sz = 1 << (fnzb(size - 1) + 1);
if (last_allocated == 0)
last_allocated = get_max_heap_addr();
/*
* Make sure we allocate from naturally aligned address.
*/
i = 0;
if (!last_allocated) {
last_allocated = (void *) ALIGN_UP((void *) &_heap +
maxheapsize, asz);
} else {
last_allocated = (void *) ALIGN_UP(((uintptr_t)
last_allocated) + (int) (i > 0), asz);
}
 
res = last_allocated;
last_allocated += ALIGN_UP(sz, PAGE_SIZE);
 
return res;
uintptr_t res = ALIGN_UP(last_allocated, sz);
last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
return ((void *) res);
}
 
/** @}
/branches/network/uspace/lib/libc/generic/string.c
589,7 → 589,7
*
* @return Pointer to character in @a str or NULL if not found.
*/
const char *str_chr(const char *str, wchar_t ch)
char *str_chr(const char *str, wchar_t ch)
{
wchar_t acc;
size_t off = 0;
597,7 → 597,7
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
return (str + last);
return (char *) (str + last);
last = off;
}
611,7 → 611,7
*
* @return Pointer to character in @a str or NULL if not found.
*/
const char *str_rchr(const char *str, wchar_t ch)
char *str_rchr(const char *str, wchar_t ch)
{
wchar_t acc;
size_t off = 0;
624,7 → 624,7
last = off;
}
return res;
return (char *) res;
}
 
/** Insert a wide character into a wide string.
/branches/network/uspace/lib/libc/generic/malloc.c
0,0 → 1,475
/*
* Copyright (c) 2009 Martin Decky
* Copyright (c) 2009 Petr Tuma
* 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 <malloc.h>
#include <bool.h>
#include <as.h>
#include <align.h>
#include <macros.h>
#include <assert.h>
#include <errno.h>
#include <bitops.h>
#include <mem.h>
#include <adt/gcdlcm.h>
 
/* Magic used in heap headers. */
#define HEAP_BLOCK_HEAD_MAGIC 0xBEEF0101
 
/* Magic used in heap footers. */
#define HEAP_BLOCK_FOOT_MAGIC 0xBEEF0202
 
/** Allocation alignment (this also covers the alignment of fields
in the heap header and footer) */
#define BASE_ALIGN 16
 
/**
* Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
*/
#define MAX_HEAP_SIZE (sizeof(uintptr_t) << 28)
 
/**
*
*/
#define STRUCT_OVERHEAD (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
 
/**
* Calculate real size of a heap block (with header and footer)
*/
#define GROSS_SIZE(size) ((size) + STRUCT_OVERHEAD)
 
/**
* Calculate net size of a heap block (without header and footer)
*/
#define NET_SIZE(size) ((size) - STRUCT_OVERHEAD)
 
 
/** Header of a heap block
*
*/
typedef struct {
/* Size of the block (including header and footer) */
size_t size;
/* Indication of a free block */
bool free;
/* A magic value to detect overwrite of heap header */
uint32_t magic;
} heap_block_head_t;
 
/** Footer of a heap block
*
*/
typedef struct {
/* Size of the block (including header and footer) */
size_t size;
/* A magic value to detect overwrite of heap footer */
uint32_t magic;
} heap_block_foot_t;
 
/** Linker heap symbol */
extern char _heap;
 
/** Address of heap start */
static void *heap_start = 0;
 
/** Address of heap end */
static void *heap_end = 0;
 
/** Maximum heap size */
static size_t max_heap_size = (size_t) -1;
 
/** Current number of pages of heap area */
static size_t heap_pages = 0;
 
/** Initialize a heap block
*
* Fills in the structures related to a heap block.
*
* @param addr Address of the block.
* @param size Size of the block including the header and the footer.
* @param free Indication of a free block.
*
*/
static void block_init(void *addr, size_t size, bool free)
{
/* Calculate the position of the header and the footer */
heap_block_head_t *head = (heap_block_head_t *) addr;
heap_block_foot_t *foot =
(heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
head->size = size;
head->free = free;
head->magic = HEAP_BLOCK_HEAD_MAGIC;
foot->size = size;
foot->magic = HEAP_BLOCK_FOOT_MAGIC;
}
 
/** Check a heap block
*
* Verifies that the structures related to a heap block still contain
* the magic constants. This helps detect heap corruption early on.
*
* @param addr Address of the block.
*
*/
static void block_check(void *addr)
{
heap_block_head_t *head = (heap_block_head_t *) addr;
assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
heap_block_foot_t *foot =
(heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
assert(head->size == foot->size);
}
 
static bool grow_heap(size_t size)
{
if (size == 0)
return false;
size_t heap_size = (size_t) (heap_end - heap_start);
if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
return false;
size_t pages = (size - 1) / PAGE_SIZE + 1;
if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
== EOK) {
void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
(heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
block_init(heap_end, end - heap_end, true);
heap_pages += pages;
heap_end = end;
return true;
}
return false;
}
 
static void shrink_heap(void)
{
// TODO
}
 
/** Initialize the heap allocator
*
* Finds how much physical memory we have and creates
* the heap management structures that mark the whole
* physical memory as a single free block.
*
*/
void __heap_init(void)
{
if (as_area_create((void *) &_heap, PAGE_SIZE,
AS_AREA_WRITE | AS_AREA_READ)) {
heap_pages = 1;
heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
heap_end =
(void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
/* Make the entire area one large block. */
block_init(heap_start, heap_end - heap_start, true);
}
}
 
uintptr_t get_max_heap_addr(void)
{
if (max_heap_size == (size_t) -1)
max_heap_size =
max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
return ((uintptr_t) heap_start + max_heap_size);
}
 
static void split_mark(heap_block_head_t *cur, const size_t size)
{
assert(cur->size >= size);
/* See if we should split the block. */
size_t split_limit = GROSS_SIZE(size);
if (cur->size > split_limit) {
/* Block big enough -> split. */
void *next = ((void *) cur) + size;
block_init(next, cur->size - size, true);
block_init(cur, size, false);
} else {
/* Block too small -> use as is. */
cur->free = false;
}
}
 
/** Allocate a memory block
*
* @param size The size of the block to allocate.
* @param align Memory address alignment.
*
* @return the address of the block or NULL when not enough memory.
*
*/
static void *malloc_internal(const size_t size, const size_t align)
{
if (align == 0)
return NULL;
size_t falign = lcm(align, BASE_ALIGN);
size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
bool grown = false;
void *result;
loop:
result = NULL;
heap_block_head_t *cur = (heap_block_head_t *) heap_start;
while ((result == NULL) && ((void *) cur < heap_end)) {
block_check(cur);
/* Try to find a block that is free and large enough. */
if ((cur->free) && (cur->size >= real_size)) {
/* We have found a suitable block.
Check for alignment properties. */
void *addr = ((void *) cur) + sizeof(heap_block_head_t);
void *aligned = (void *) ALIGN_UP(addr, falign);
if (addr == aligned) {
/* Exact block start including alignment. */
split_mark(cur, real_size);
result = addr;
} else {
/* Block start has to be aligned */
size_t excess = (size_t) (aligned - addr);
if (cur->size >= real_size + excess) {
/* The current block is large enough to fit
data in including alignment */
if ((void *) cur > heap_start) {
/* There is a block before the current block.
This previous block can be enlarged to compensate
for the alignment excess */
heap_block_foot_t *prev_foot =
((void *) cur) - sizeof(heap_block_foot_t);
heap_block_head_t *prev_head =
(heap_block_head_t *) (((void *) cur) - prev_foot->size);
block_check(prev_head);
size_t reduced_size = cur->size - excess;
heap_block_head_t *next_head = ((void *) cur) + excess;
if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
/* The previous block is not free and there is enough
space to fill in a new free block between the previous
and current block */
block_init(cur, excess, true);
} else {
/* The previous block is free (thus there is no need to
induce additional fragmentation to the heap) or the
excess is small, thus just enlarge the previous block */
block_init(prev_head, prev_head->size + excess, prev_head->free);
}
block_init(next_head, reduced_size, true);
split_mark(next_head, real_size);
result = aligned;
cur = next_head;
} else {
/* The current block is the first block on the heap.
We have to make sure that the alignment excess
is large enough to fit a new free block just
before the current block */
while (excess < STRUCT_OVERHEAD) {
aligned += falign;
excess += falign;
}
/* Check for current block size again */
if (cur->size >= real_size + excess) {
size_t reduced_size = cur->size - excess;
cur = (heap_block_head_t *) (heap_start + excess);
block_init(heap_start, excess, true);
block_init(cur, reduced_size, true);
split_mark(cur, real_size);
result = aligned;
}
}
}
}
}
/* Advance to the next block. */
cur = (heap_block_head_t *) (((void *) cur) + cur->size);
}
if ((result == NULL) && (!grown)) {
if (grow_heap(real_size)) {
grown = true;
goto loop;
}
}
return result;
}
 
void *malloc(const size_t size)
{
return malloc_internal(size, BASE_ALIGN);
}
 
void *memalign(const size_t align, const size_t size)
{
if (align == 0)
return NULL;
size_t palign =
1 << (fnzb(max(sizeof(void *), align) - 1) + 1);
return malloc_internal(size, palign);
}
 
void *realloc(const void *addr, const size_t size)
{
if (addr == NULL)
return malloc(size);
/* Calculate the position of the header. */
heap_block_head_t *head =
(heap_block_head_t *) (addr - sizeof(heap_block_head_t));
assert((void *) head >= heap_start);
assert((void *) head < heap_end);
block_check(head);
assert(!head->free);
void *ptr = NULL;
size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
size_t orig_size = head->size;
if (orig_size > real_size) {
/* Shrink */
if (orig_size - real_size >= STRUCT_OVERHEAD) {
/* Split the original block to a full block
and a tailing free block */
block_init((void *) head, real_size, false);
block_init((void *) head + real_size,
orig_size - real_size, true);
shrink_heap();
}
ptr = ((void *) head) + sizeof(heap_block_head_t);
} else {
/* Look at the next block. If it is free and the size is
sufficient then merge the two. */
heap_block_head_t *next_head =
(heap_block_head_t *) (((void *) head) + head->size);
if (((void *) next_head < heap_end) &&
(head->size + next_head->size >= real_size) &&
(next_head->free)) {
block_check(next_head);
block_init(head, head->size + next_head->size, false);
split_mark(head, real_size);
ptr = ((void *) head) + sizeof(heap_block_head_t);
} else {
ptr = malloc(size);
if (ptr != NULL) {
memcpy(ptr, addr, NET_SIZE(orig_size));
free(addr);
}
}
}
return ptr;
}
 
/** Free a memory block
*
* @param addr The address of the block.
*/
void free(const void *addr)
{
/* Calculate the position of the header. */
heap_block_head_t *head
= (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
assert((void *) head >= heap_start);
assert((void *) head < heap_end);
block_check(head);
assert(!head->free);
/* Mark the block itself as free. */
head->free = true;
/* Look at the next block. If it is free, merge the two. */
heap_block_head_t *next_head
= (heap_block_head_t *) (((void *) head) + head->size);
if ((void *) next_head < heap_end) {
block_check(next_head);
if (next_head->free)
block_init(head, head->size + next_head->size, true);
}
/* Look at the previous block. If it is free, merge the two. */
if ((void *) head > heap_start) {
heap_block_foot_t *prev_foot =
(heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
heap_block_head_t *prev_head =
(heap_block_head_t *) (((void *) head) - prev_foot->size);
block_check(prev_head);
if (prev_head->free)
block_init(prev_head, prev_head->size + head->size, true);
}
shrink_heap();
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/libc.c
52,11 → 52,8
#include <as.h>
#include <loader/pcb.h>
 
extern char _heap;
extern int main(int argc, char *argv[]);
 
int _errno;
 
void _exit(int status)
{
thread_exit(status);
64,9 → 61,10
 
void __main(void *pcb_ptr)
{
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ);
_async_init();
int retval;
 
__heap_init();
__async_init();
fibril_t *fibril = fibril_setup();
__tcb_set(fibril->tcb);
79,15 → 77,17
if (__pcb == NULL) {
argc = 0;
argv = NULL;
stdio_init(0, NULL);
__stdio_init(0, NULL);
} else {
argc = __pcb->argc;
argv = __pcb->argv;
stdio_init(__pcb->filc, __pcb->filv);
__stdio_init(__pcb->filc, __pcb->filv);
}
main(argc, argv);
stdio_done();
retval = main(argc, argv);
 
__stdio_done();
(void) task_retval(retval);
}
 
void __exit(void)
/branches/network/uspace/lib/libc/generic/devmap.c
218,6 → 218,31
return phone;
}
 
int devmap_null_create(void)
{
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
if (phone < 0)
return -1;
ipcarg_t null_id;
int retval = async_req_0_1(phone, DEVMAP_DEVICE_NULL_CREATE, &null_id);
if (retval != EOK)
return -1;
return (int) null_id;
}
 
void devmap_null_destroy(int null_id)
{
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
if (phone < 0)
return;
async_req_1_0(phone, DEVMAP_DEVICE_NULL_DESTROY, (ipcarg_t) null_id);
}
 
ipcarg_t devmap_device_get_count(void)
{
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
/branches/network/uspace/lib/libc/generic/async.c
738,7 → 738,7
*
* @return Zero on success or an error code.
*/
int _async_init(void)
int __async_init(void)
{
if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1,
&conn_hash_table_ops)) {
/branches/network/uspace/lib/libc/generic/vfs/vfs.c
38,8 → 38,8
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/types.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
137,7 → 137,7
async_serialize_start();
vfs_connect();
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL);
req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
198,7 → 198,7
async_serialize_start();
vfs_connect();
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
230,7 → 230,7
vfs_connect();
ipc_call_t answer;
aid_t req = async_send_4(vfs_phone, VFS_OPEN_NODE, node->fs_handle,
aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
node->dev_handle, node->index, oflag, &answer);
ipcarg_t rc;
252,7 → 252,7
async_serialize_start();
vfs_connect();
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
async_serialize_end();
futex_up(&vfs_phone_futex);
270,7 → 270,7
async_serialize_start();
vfs_connect();
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
async_wait_for(req, NULL);
297,7 → 297,7
async_serialize_start();
vfs_connect();
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
async_wait_for(req, NULL);
314,95 → 314,115
return -1;
}
 
int fd_phone(int fildes)
int fsync(int fildes)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t device;
ipcarg_t rc = async_req_1_1(vfs_phone, VFS_DEVICE, fildes, &device);
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc != EOK)
return -1;
return devmap_device_connect((dev_handle_t) device, 0);
return (int) rc;
}
 
int fd_node(int fildes, fdi_node_t *node)
off_t lseek(int fildes, off_t offset, int whence)
{
ipcarg_t rc;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t fs_handle;
ipcarg_t dev_handle;
ipcarg_t index;
ipcarg_t rc = async_req_1_3(vfs_phone, VFS_NODE, fildes, &fs_handle,
&dev_handle, &index);
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
&newoffs);
 
async_serialize_end();
futex_up(&vfs_phone_futex);
 
if (rc != EOK)
return (off_t) -1;
if (rc == EOK) {
node->fs_handle = (fs_handle_t) fs_handle;
node->dev_handle = (dev_handle_t) dev_handle;
node->index = (fs_index_t) index;
}
return rc;
return (off_t) newoffs;
}
 
int fsync(int fildes)
int ftruncate(int fildes, off_t length)
{
ipcarg_t rc;
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_SYNC, fildes);
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (int) rc;
}
 
off_t lseek(int fildes, off_t offset, int whence)
int fstat(int fildes, struct stat *stat)
{
ipcarg_t rc;
aid_t req;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
&newoffs);
 
req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (ssize_t) rc;
}
async_wait_for(req, &rc);
async_serialize_end();
futex_up(&vfs_phone_futex);
 
if (rc != EOK)
return (off_t) -1;
return (off_t) newoffs;
return rc;
}
 
int ftruncate(int fildes, off_t length)
int stat(const char *path, struct stat *stat)
{
ipcarg_t rc;
aid_t req;
size_t pa_size;
char *pa = absolutize(path, &pa_size);
if (!pa)
return ENOMEM;
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return (int) rc;
}
rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return (int) rc;
}
async_wait_for(req, &rc);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (int) rc;
free(pa);
return rc;
}
 
DIR *opendir(const char *dirname)
452,7 → 472,7
async_serialize_start();
vfs_connect();
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
482,7 → 502,7
async_serialize_start();
vfs_connect();
req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
529,7 → 549,7
async_serialize_start();
vfs_connect();
req = async_send_0(vfs_phone, VFS_RENAME, NULL);
req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
rc = ipc_data_write_start(vfs_phone, olda, olda_size);
if (rc != EOK) {
async_wait_for(req, NULL);
598,5 → 618,34
return buf;
}
 
int fd_phone(int fildes)
{
struct stat stat;
int rc;
 
rc = fstat(fildes, &stat);
 
if (!stat.devfs_stat.device)
return -1;
return devmap_device_connect(stat.devfs_stat.device, 0);
}
 
int fd_node(int fildes, fdi_node_t *node)
{
struct stat stat;
int rc;
 
rc = fstat(fildes, &stat);
if (rc == EOK) {
node->fs_handle = stat.fs_handle;
node->dev_handle = stat.dev_handle;
node->index = stat.index;
}
return rc;
}
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/errno.c
0,0 → 1,41
/*
* 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
*/
 
#include <errno.h>
#include <fibril.h>
 
int _errno;
 
/** @}
*/
/branches/network/uspace/lib/libc/generic/io/console.c
69,6 → 69,17
async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false);
}
 
int console_get_color_cap(int phone, int *ccap)
{
ipcarg_t ccap_tmp;
int rc;
 
rc = async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, &ccap_tmp);
*ccap = ccap_tmp;
 
return rc;
}
 
void console_kcon_enable(int phone)
{
async_msg_0(phone, CONSOLE_KCON_ENABLE);
/branches/network/uspace/lib/libc/generic/io/io.c
89,7 → 89,7
 
static LIST_INITIALIZE(files);
 
void stdio_init(int filc, fdi_node_t *filv[])
void __stdio_init(int filc, fdi_node_t *filv[])
{
if (filc > 0) {
stdin = fopen_node(filv[0], "r");
113,7 → 113,7
}
}
 
void stdio_done(void)
void __stdio_done(void)
{
link_t *link = files.next;
180,17 → 180,34
stream->buf_head = stream->buf;
}
 
static void _setvbuf(FILE *stream)
{
/* FIXME: Use more complex rules for setting buffering options. */
switch (stream->fd) {
case 1:
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
break;
case 0:
case 2:
setvbuf(stream, NULL, _IONBF, 0);
break;
default:
setvbuf(stream, NULL, _IOFBF, BUFSIZ);
}
}
 
/** Allocate stream buffer. */
static int _fallocbuf(FILE *stream)
{
assert(stream->buf == NULL);
 
stream->buf = malloc(stream->buf_size);
if (stream->buf == NULL) {
errno = ENOMEM;
return -1;
}
 
stream->buf_head = stream->buf;
return 0;
}
225,9 → 242,7
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOFBF, BUFSIZ);
_setvbuf(stream);
list_append(&stream->link, &files);
248,9 → 263,7
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
_setvbuf(stream);
list_append(&stream->link, &files);
281,9 → 294,7
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
_setvbuf(stream);
list_append(&stream->link, &files);
331,10 → 342,10
{
size_t left = size * nmemb;
size_t done = 0;
 
/* Make sure no data is pending write. */
_fflushbuf(stream);
 
while ((left > 0) && (!stream->error) && (!stream->eof)) {
ssize_t rd = read(stream->fd, buf + done, left);
379,14 → 390,14
static void _fflushbuf(FILE *stream)
{
size_t bytes_used;
 
if (!stream->buf || stream->btype == _IONBF || stream->error)
if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error))
return;
 
bytes_used = stream->buf_head - stream->buf;
if (bytes_used == 0)
return;
 
(void) _fwrite(stream->buf, 1, bytes_used, stream);
stream->buf_head = stream->buf;
}
409,44 → 420,46
size_t i;
uint8_t b;
bool need_flush;
 
/* If not buffered stream, write out directly. */
if (stream->btype == _IONBF)
return _fwrite(buf, size, nmemb, stream);
 
if (stream->btype == _IONBF) {
now = _fwrite(buf, size, nmemb, stream);
fflush(stream);
return now;
}
/* Perform lazy allocation of stream buffer. */
if (stream->buf == NULL) {
if (_fallocbuf(stream) != 0)
return 0; /* Errno set by _fallocbuf(). */
}
 
data = (uint8_t *) buf;
bytes_left = size * nmemb;
total_written = 0;
need_flush = false;
 
while (!stream->error && bytes_left > 0) {
 
while ((!stream->error) && (bytes_left > 0)) {
buf_free = stream->buf_size - (stream->buf_head - stream->buf);
if (bytes_left > buf_free)
now = buf_free;
else
now = bytes_left;
 
for (i = 0; i < now; i++) {
b = data[i];
stream->buf_head[i] = b;
 
if (b == '\n' && stream->btype == _IOLBF)
if ((b == '\n') && (stream->btype == _IOLBF))
need_flush = true;
}
 
buf += now;
stream->buf_head += now;
buf_free -= now;
bytes_left -= now;
total_written += now;
 
if (buf_free == 0) {
/* Only need to drain buffer. */
_fflushbuf(stream);
453,10 → 466,10
need_flush = false;
}
}
 
if (need_flush)
fflush(stream);
 
return (total_written / size);
}
 
495,13 → 508,13
int fgetc(FILE *stream)
{
char c;
 
/* This could be made faster by only flushing when needed. */
if (stdout)
fflush(stdout);
if (stderr)
fflush(stderr);
 
if (fread(&c, sizeof(char), 1, stream) < sizeof(char))
return EOF;
534,7 → 547,7
int fflush(FILE *stream)
{
_fflushbuf(stream);
 
if (stream->klog) {
klog_update();
return EOK;
/branches/network/uspace/lib/libc/generic/mman.c
37,17 → 37,18
#include <as.h>
#include <unistd.h>
 
void *mmap(void *start, size_t length, int prot, int flags, int fd,
void *mmap(void *start, size_t length, int prot, int flags, int fd,
off_t offset)
{
if (!start)
start = as_get_mappable_page(length);
// if (! ((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE)))
// if (!((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE)))
// return MAP_FAILED;
if (! (flags & MAP_ANONYMOUS))
if (!(flags & MAP_ANONYMOUS))
return MAP_FAILED;
 
return as_area_create(start, length, prot);
}