Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4389 → Rev 4691

/branches/dynload/uspace/lib/libfs/libfs.c
1,5 → 1,5
/*
* Copyright (c) 2008 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
42,6 → 42,8
#include <as.h>
#include <assert.h>
#include <dirent.h>
#include <mem.h>
#include <sys/stat.h>
 
/** Register file system server.
*
68,7 → 70,7
* out-of-order, when it knows that the operation succeeded or failed.
*/
ipc_call_t answer;
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer);
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer);
 
/*
* Send our VFS info structure to VFS.
103,7 → 105,7
}
/*
* Pick up the answer for the request to the VFS_REQUEST call.
* Pick up the answer for the request to the VFS_IN_REQUEST call.
*/
async_wait_for(req, NULL);
reg->fs_handle = (int) IPC_GET_ARG1(answer);
122,23 → 124,106
return IPC_GET_RETVAL(answer);
}
 
void fs_node_initialize(fs_node_t *fn)
{
memset(fn, 0, sizeof(fs_node_t));
}
 
void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request);
int res;
ipcarg_t rc;
 
ipc_call_t call;
ipc_callid_t callid;
 
/* accept the phone */
callid = async_get_call(&call);
int mountee_phone = (int)IPC_GET_ARG1(call);
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) ||
mountee_phone < 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */
res = ipc_data_write_receive(&callid, NULL);
if (!res) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index);
if (!fn) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
return;
}
 
if (fn->mp_data.mp_active) {
ipc_hangup(mountee_phone);
ops->node_put(fn);
ipc_answer_0(callid, EBUSY);
ipc_answer_0(rid, EBUSY);
return;
}
 
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
if (rc != 0) {
ipc_hangup(mountee_phone);
ops->node_put(fn);
ipc_answer_0(callid, rc);
ipc_answer_0(rid, rc);
return;
}
ipc_call_t answer;
aid_t msg = async_send_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle,
&answer);
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
async_wait_for(msg, &rc);
if (rc == EOK) {
fn->mp_data.mp_active = true;
fn->mp_data.fs_handle = mr_fs_handle;
fn->mp_data.dev_handle = mr_dev_handle;
fn->mp_data.phone = mountee_phone;
}
/*
* Do not release the FS node so that it stays in memory.
*/
ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
IPC_GET_ARG3(answer));
}
 
/** Lookup VFS triplet by name in the file system name space.
*
* The path passed in the PLB must be in the canonical file system path format
* as returned by the canonify() function.
*
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param fs_handle File system handle of the file system where to perform
* the lookup.
* @param rid Request ID of the VFS_LOOKUP request.
* @param request VFS_LOOKUP request data itself.
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param fs_handle File system handle of the file system where to perform
* the lookup.
* @param rid Request ID of the VFS_OUT_LOOKUP request.
* @param request VFS_OUT_LOOKUP request data itself.
*
*/
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
unsigned next = IPC_GET_ARG1(*request);
unsigned first = IPC_GET_ARG1(*request);
unsigned last = IPC_GET_ARG2(*request);
unsigned next = first;
dev_handle_t dev_handle = IPC_GET_ARG3(*request);
int lflag = IPC_GET_ARG4(*request);
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
152,6 → 237,14
fs_node_t *cur = ops->root_get(dev_handle);
fs_node_t *tmp = NULL;
 
if (cur->mp_data.mp_active) {
ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
next, last, cur->mp_data.dev_handle, lflag, index,
IPC_FF_ROUTE_FROM_ME);
ops->node_put(cur);
return;
}
 
if (ops->plb_get_char(next) == '/')
next++; /* eat slash */
174,6 → 267,21
 
/* match the component */
tmp = ops->match(cur, component);
if (tmp && tmp->mp_data.mp_active) {
if (next > last)
next = last = first;
else
next--;
ipc_forward_slow(rid, tmp->mp_data.phone,
VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle,
lflag, index, IPC_FF_ROUTE_FROM_ME);
ops->node_put(cur);
ops->node_put(tmp);
if (par)
ops->node_put(par);
return;
}
 
/* handle miss: match amongst siblings */
if (!tmp) {
321,5 → 429,62
ops->node_put(tmp);
}
 
void libfs_stat(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
fs_node_t *fn = ops->node_get(dev_handle, index);
 
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size) ||
size != sizeof(struct stat)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
struct stat stat;
memset(&stat, 0, sizeof(struct stat));
stat.fs_handle = fs_handle;
stat.dev_handle = dev_handle;
stat.index = index;
stat.lnkcnt = ops->lnkcnt_get(fn);
stat.is_file = ops->is_file(fn);
stat.size = ops->size_get(fn);
 
ipc_data_read_finalize(callid, &stat, sizeof(struct stat));
ipc_answer_0(rid, EOK);
}
 
/** Open VFS triplet.
*
* @param ops libfs operations structure with function pointers to
* file system implementation
* @param rid Request ID of the VFS_OUT_OPEN_NODE request.
* @param request VFS_OUT_OPEN_NODE request data itself.
*
*/
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
ipc_call_t *request)
{
dev_handle_t dev_handle = IPC_GET_ARG1(*request);
fs_index_t index = IPC_GET_ARG2(*request);
fs_node_t *node = ops->node_get(dev_handle, index);
if (node == NULL) {
ipc_answer_0(rid, ENOENT);
return;
}
ipc_answer_5(rid, EOK, fs_handle, dev_handle, index,
ops->size_get(node), ops->lnkcnt_get(node));
ops->node_put(node);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libfs/libfs.h
1,5 → 1,5
/*
* Copyright (c) 2007 Jakub Jermar
* Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
26,23 → 26,32
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libfs
/** @addtogroup libfs
* @{
*/
*/
/**
* @file
*/
 
#ifndef LIBFS_LIBFS_H_
#define LIBFS_LIBFS_H_
#define LIBFS_LIBFS_H_
 
#include "../../srv/vfs/vfs.h"
#include <ipc/vfs.h>
#include <stdint.h>
#include <ipc/ipc.h>
#include <async.h>
#include <devmap.h>
 
typedef struct {
void *data; /**< Data of the file system implementation. */
bool mp_active;
int phone;
fs_handle_t fs_handle;
dev_handle_t dev_handle;
} mp_data_t;
 
typedef struct {
mp_data_t mp_data; /**< Mount point info. */
void *data; /**< Data of the file system implementation. */
} fs_node_t;
 
typedef struct {
58,23 → 67,28
unsigned (* lnkcnt_get)(fs_node_t *);
bool (* has_children)(fs_node_t *);
fs_node_t *(* root_get)(dev_handle_t);
char (* plb_get_char)(unsigned pos);
char (* plb_get_char)(unsigned pos);
bool (* is_directory)(fs_node_t *);
bool (* is_file)(fs_node_t *);
} libfs_ops_t;
 
typedef struct {
int fs_handle; /**< File system handle. */
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
uint8_t *plb_ro; /**< Read-only PLB view. */
int fs_handle; /**< File system handle. */
ipcarg_t vfs_phonehash; /**< Initial VFS phonehash. */
uint8_t *plb_ro; /**< Read-only PLB view. */
} fs_reg_t;
 
extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t);
 
extern void fs_node_initialize(fs_node_t *);
 
extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
extern void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
ipc_call_t *);
 
#endif
 
/** @}
*/
 
/branches/dynload/uspace/lib/libblock/libblock.c
37,8 → 37,8
 
#include "libblock.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <ipc/devmap.h>
#include <ipc/bd.h>
#include <ipc/services.h>
#include <errno.h>
#include <sys/mman.h>
46,12 → 46,13
#include <ipc/ipc.h>
#include <as.h>
#include <assert.h>
#include <futex.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <adt/hash_table.h>
#include <mem.h>
 
/** Lock protecting the device connection list */
static futex_t dcl_lock = FUTEX_INITIALIZER;
static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
/** Device connection list head. */
static LIST_INITIALIZE(dcl_head);
 
59,17 → 60,20
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)
 
typedef struct {
futex_t lock;
fibril_mutex_t lock;
size_t block_size; /**< Block size. */
unsigned block_count; /**< Total number of blocks. */
unsigned blocks_cached; /**< Number of cached blocks. */
hash_table_t block_hash;
link_t free_head;
enum cache_mode mode;
} cache_t;
 
typedef struct {
link_t link;
int dev_handle;
dev_handle_t dev_handle;
int dev_phone;
fibril_mutex_t com_area_lock;
void *com_area;
size_t com_size;
void *bb_buf;
78,19 → 82,22
cache_t *cache;
} devcon_t;
 
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size);
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size);
 
static devcon_t *devcon_search(dev_handle_t dev_handle)
{
link_t *cur;
 
futex_down(&dcl_lock);
fibril_mutex_lock(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
devcon_t *devcon = list_get_instance(cur, devcon_t, link);
if (devcon->dev_handle == dev_handle) {
futex_up(&dcl_lock);
fibril_mutex_unlock(&dcl_lock);
return devcon;
}
}
futex_up(&dcl_lock);
fibril_mutex_unlock(&dcl_lock);
return NULL;
}
 
107,6 → 114,7
link_initialize(&devcon->link);
devcon->dev_handle = dev_handle;
devcon->dev_phone = dev_phone;
fibril_mutex_initialize(&devcon->com_area_lock);
devcon->com_area = com_area;
devcon->com_size = com_size;
devcon->bb_buf = NULL;
114,25 → 122,25
devcon->bb_size = 0;
devcon->cache = NULL;
 
futex_down(&dcl_lock);
fibril_mutex_lock(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
devcon_t *d = list_get_instance(cur, devcon_t, link);
if (d->dev_handle == dev_handle) {
futex_up(&dcl_lock);
fibril_mutex_unlock(&dcl_lock);
free(devcon);
return EEXIST;
}
}
list_append(&devcon->link, &dcl_head);
futex_up(&dcl_lock);
fibril_mutex_unlock(&dcl_lock);
return EOK;
}
 
static void devcon_remove(devcon_t *devcon)
{
futex_down(&dcl_lock);
fibril_mutex_lock(&dcl_lock);
list_remove(&devcon->link);
futex_up(&dcl_lock);
fibril_mutex_unlock(&dcl_lock);
}
 
int block_init(dev_handle_t dev_handle, size_t com_size)
146,9 → 154,8
if (!com_area) {
return ENOMEM;
}
dev_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
if (dev_phone < 0) {
munmap(com_area, com_size);
return dev_phone;
207,14 → 214,16
if (!bb_buf)
return ENOMEM;
off_t bufpos = 0;
size_t buflen = 0;
rc = block_read(dev_handle, &bufpos, &buflen, &off,
bb_buf, size, size);
fibril_mutex_lock(&devcon->com_area_lock);
rc = read_block(devcon, 0, size);
if (rc != EOK) {
fibril_mutex_unlock(&devcon->com_area_lock);
free(bb_buf);
return rc;
}
memcpy(bb_buf, devcon->com_area, size);
fibril_mutex_unlock(&devcon->com_area_lock);
 
devcon->bb_buf = bb_buf;
devcon->bb_off = off;
devcon->bb_size = size;
250,7 → 259,8
.remove_callback = cache_remove_callback
};
 
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks)
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks,
enum cache_mode mode)
{
devcon_t *devcon = devcon_search(dev_handle);
cache_t *cache;
262,10 → 272,12
if (!cache)
return ENOMEM;
futex_initialize(&cache->lock, 1);
fibril_mutex_initialize(&cache->lock);
list_initialize(&cache->free_head);
cache->block_size = size;
cache->block_count = blocks;
cache->blocks_cached = 0;
cache->mode = mode;
 
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
&cache_ops)) {
277,17 → 289,23
return EOK;
}
 
#define CACHE_LO_WATERMARK 10
#define CACHE_HI_WATERMARK 20
static bool cache_can_grow(cache_t *cache)
{
if (cache->blocks_cached < CACHE_LO_WATERMARK)
return true;
if (!list_empty(&cache->free_head))
return false;
return true;
}
 
static void block_initialize(block_t *b)
{
futex_initialize(&b->lock, 1);
fibril_mutex_initialize(&b->lock);
b->refcnt = 1;
b->dirty = false;
rwlock_initialize(&b->contents_lock);
fibril_rwlock_initialize(&b->contents_lock);
link_initialize(&b->free_link);
link_initialize(&b->hash_link);
}
309,6 → 327,7
block_t *b;
link_t *l;
unsigned long key = boff;
bn_t oboff;
devcon = devcon_search(dev_handle);
 
316,7 → 335,7
assert(devcon->cache);
cache = devcon->cache;
futex_down(&cache->lock);
fibril_mutex_lock(&cache->lock);
l = hash_table_find(&cache->block_hash, &key);
if (l) {
/*
323,19 → 342,16
* We found the block in the cache.
*/
b = hash_table_get_instance(l, block_t, hash_link);
futex_down(&b->lock);
fibril_mutex_lock(&b->lock);
if (b->refcnt++ == 0)
list_remove(&b->free_link);
futex_up(&b->lock);
futex_up(&cache->lock);
fibril_mutex_unlock(&b->lock);
fibril_mutex_unlock(&cache->lock);
} else {
/*
* The block was not found in the cache.
*/
int rc;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = boff * cache->block_size;
bool sync = false;
 
if (cache_can_grow(cache)) {
352,6 → 368,7
free(b);
goto recycle;
}
cache->blocks_cached++;
} else {
/*
* Try to recycle a block from the free list.
361,8 → 378,9
assert(!list_empty(&cache->free_head));
l = cache->free_head.next;
list_remove(l);
b = hash_table_get_instance(l, block_t, hash_link);
b = list_get_instance(l, block_t, free_link);
sync = b->dirty;
oboff = b->boff;
temp_key = b->boff;
hash_table_remove(&cache->block_hash, &temp_key, 1);
}
378,8 → 396,8
* kill concurent operations on the cache while doing I/O on the
* block.
*/
futex_down(&b->lock);
futex_up(&cache->lock);
fibril_mutex_lock(&b->lock);
fibril_mutex_unlock(&cache->lock);
 
if (sync) {
/*
386,7 → 404,11
* The block is dirty and needs to be written back to
* the device before we can read in the new contents.
*/
abort(); /* TODO: block_write() */
fibril_mutex_lock(&devcon->com_area_lock);
memcpy(devcon->com_area, b->data, b->size);
rc = write_block(devcon, oboff, cache->block_size);
assert(rc == EOK);
fibril_mutex_unlock(&devcon->com_area_lock);
}
if (!(flags & BLOCK_FLAGS_NOREAD)) {
/*
393,12 → 415,14
* The block contains old or no data. We need to read
* the new contents from the device.
*/
rc = block_read(dev_handle, &bufpos, &buflen, &pos,
b->data, cache->block_size, cache->block_size);
fibril_mutex_lock(&devcon->com_area_lock);
rc = read_block(devcon, b->boff, cache->block_size);
assert(rc == EOK);
memcpy(b->data, devcon->com_area, cache->block_size);
fibril_mutex_unlock(&devcon->com_area_lock);
}
 
futex_up(&b->lock);
fibril_mutex_unlock(&b->lock);
}
return b;
}
413,25 → 437,62
{
devcon_t *devcon = devcon_search(block->dev_handle);
cache_t *cache;
int rc;
 
assert(devcon);
assert(devcon->cache);
 
cache = devcon->cache;
futex_down(&cache->lock);
futex_down(&block->lock);
fibril_mutex_lock(&cache->lock);
fibril_mutex_lock(&block->lock);
if (!--block->refcnt) {
/*
* Last reference to the block was dropped, put the block on the
* free list.
* Last reference to the block was dropped. Either free the
* block or put it on the free list.
*/
if (cache->blocks_cached > CACHE_HI_WATERMARK) {
/*
* Currently there are too many cached blocks.
*/
if (block->dirty) {
fibril_mutex_lock(&devcon->com_area_lock);
memcpy(devcon->com_area, block->data,
block->size);
rc = write_block(devcon, block->boff,
block->size);
assert(rc == EOK);
fibril_mutex_unlock(&devcon->com_area_lock);
}
/*
* Take the block out of the cache and free it.
*/
unsigned long key = block->boff;
hash_table_remove(&cache->block_hash, &key, 1);
free(block);
free(block->data);
cache->blocks_cached--;
fibril_mutex_unlock(&cache->lock);
return;
}
/*
* Put the block on the free list.
*/
list_append(&block->free_link, &cache->free_head);
if (cache->mode != CACHE_MODE_WB && block->dirty) {
fibril_mutex_lock(&devcon->com_area_lock);
memcpy(devcon->com_area, block->data, block->size);
rc = write_block(devcon, block->boff, block->size);
assert(rc == EOK);
fibril_mutex_unlock(&devcon->com_area_lock);
 
block->dirty = false;
}
}
futex_up(&block->lock);
futex_up(&cache->lock);
fibril_mutex_unlock(&block->lock);
fibril_mutex_unlock(&cache->lock);
}
 
/** Read data from a block device.
/** Read sequential data from a block device.
*
* @param dev_handle Device handle of the block device.
* @param bufpos Pointer to the first unread valid offset within the
445,9 → 506,8
*
* @return EOK on success or a negative return code on failure.
*/
int
block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst,
size_t size, size_t block_size)
int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen,
off_t *pos, void *dst, size_t size, size_t block_size)
{
off_t offset = 0;
size_t left = size;
454,6 → 514,7
devcon_t *devcon = devcon_search(dev_handle);
assert(devcon);
fibril_mutex_lock(&devcon->com_area_lock);
while (left > 0) {
size_t rd;
474,21 → 535,70
left -= rd;
}
if (*bufpos == *buflen) {
if (*bufpos == (off_t) *buflen) {
/* Refill the communication buffer with a new block. */
ipcarg_t retval;
int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return (rc != EOK ? rc : retval);
int rc;
 
rc = read_block(devcon, *pos / block_size, block_size);
if (rc != EOK) {
fibril_mutex_unlock(&devcon->com_area_lock);
return rc;
}
*bufpos = 0;
*buflen = block_size;
}
}
fibril_mutex_unlock(&devcon->com_area_lock);
return EOK;
}
 
/** Read block from block device.
*
* @param devcon Device connection.
* @param boff Block index.
* @param block_size Block size.
* @param src Buffer for storing the data.
*
* @return EOK on success or negative error code on failure.
*/
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size)
{
ipcarg_t retval;
int rc;
 
assert(devcon);
rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size,
&retval);
if ((rc != EOK) || (retval != EOK))
return (rc != EOK ? rc : (int) retval);
 
return EOK;
}
 
/** Write block to block device.
*
* @param devcon Device connection.
* @param boff Block index.
* @param block_size Block size.
* @param src Buffer containing the data to write.
*
* @return EOK on success or negative error code on failure.
*/
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size)
{
ipcarg_t retval;
int rc;
 
assert(devcon);
rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size,
&retval);
if ((rc != EOK) || (retval != EOK))
return (rc != EOK ? rc : (int) retval);
 
return EOK;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libblock/libblock.h
39,10 → 39,9
 
#include <stdint.h>
#include "../../srv/vfs/vfs.h"
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <adt/list.h>
 
/*
* Flags that can be used with block_get().
63,14 → 62,14
typedef unsigned bn_t; /**< Block number type. */
 
typedef struct block {
/** Futex protecting the reference count. */
futex_t lock;
/** Mutex protecting the reference count. */
fibril_mutex_t lock;
/** Number of references to the block_t structure. */
unsigned refcnt;
/** If true, the block needs to be written back to the block device. */
bool dirty;
/** Readers / Writer lock protecting the contents of the block. */
rwlock_t contents_lock;
fibril_rwlock_t contents_lock;
/** Handle of the device where the block resides. */
dev_handle_t dev_handle;
/** Block offset on the block device. Counted in 'size'-byte blocks. */
85,6 → 84,14
void *data;
} block_t;
 
/** Caching mode */
enum cache_mode {
/** Write-Through */
CACHE_MODE_WT,
/** Write-Back */
CACHE_MODE_WB
};
 
extern int block_init(dev_handle_t, size_t);
extern void block_fini(dev_handle_t);
 
91,12 → 98,13
extern int block_bb_read(dev_handle_t, off_t, size_t);
extern void *block_bb_get(dev_handle_t);
 
extern int block_cache_init(dev_handle_t, size_t, unsigned);
extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode);
 
extern block_t *block_get(dev_handle_t, bn_t, int flags);
extern block_t *block_get(dev_handle_t, bn_t, int);
extern void block_put(block_t *);
 
extern int block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *,
size_t, size_t);
 
#endif
 
/branches/dynload/uspace/lib/softfloat/include/sftypes.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup softfloat
/** @addtogroup softfloat
* @{
*/
/** @file
41,40 → 41,40
typedef union {
float f;
uint32_t binary;
 
struct {
#if defined(ARCH_IS_BIG_ENDIAN)
uint32_t sign:1;
uint32_t exp:8;
uint32_t fraction:23;
#elif defined(ARCH_IS_LITTLE_ENDIAN)
uint32_t fraction:23;
uint32_t exp:8;
uint32_t sign:1;
#else
#error "Unknown endians."
struct {
#if defined(__BE__)
uint32_t sign : 1;
uint32_t exp : 8;
uint32_t fraction : 23;
#elif defined(__LE__)
uint32_t fraction : 23;
uint32_t exp : 8;
uint32_t sign : 1;
#else
#error Unknown endianess
#endif
} parts __attribute__ ((packed));
} float32;
} float32;
 
typedef union {
double d;
uint64_t binary;
struct {
#if defined(ARCH_IS_BIG_ENDIAN)
uint64_t sign:1;
uint64_t exp:11;
uint64_t fraction:52;
#elif defined(ARCH_IS_LITTLE_ENDIAN)
uint64_t fraction:52;
uint64_t exp:11;
uint64_t sign:1;
#else
#error "Unknown endians."
struct {
#if defined(__BE__)
uint64_t sign : 1;
uint64_t exp : 11;
uint64_t fraction : 52;
#elif defined(__LE__)
uint64_t fraction : 52;
uint64_t exp : 11;
uint64_t sign : 1;
#else
#error Unknown endianess
#endif
} parts __attribute__ ((packed));
} float64;
} parts __attribute__ ((packed));
} float64;
 
#define FLOAT32_MAX 0x7f800000
#define FLOAT32_MIN 0xff800000
109,7 → 109,5
 
#endif
 
 
/** @}
/** @}
*/
 
/branches/dynload/uspace/lib/softfloat/Makefile
36,7 → 36,7
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS +=-Iinclude -Iarch/$(UARCH)/include/
CFLAGS += -Iinclude -Iarch/$(UARCH)/include/
 
## Sources
#
/branches/dynload/uspace/lib/libc/malloc/malloc.c
File deleted
/branches/dynload/uspace/lib/libc/include/console.h
File deleted
/branches/dynload/uspace/lib/libc/include/console/color.h
File deleted
/branches/dynload/uspace/lib/libc/include/console/style.h
File deleted
/branches/dynload/uspace/lib/libc/include/kbd/kbd.h
File deleted
/branches/dynload/uspace/lib/libc/include/kbd/keycode.h
File deleted
/branches/dynload/uspace/lib/libc/include/libadt/fifo.h
File deleted
/branches/dynload/uspace/lib/libc/include/libadt/hash_table.h
File deleted
/branches/dynload/uspace/lib/libc/include/libadt/list.h
File deleted
/branches/dynload/uspace/lib/libc/include/byteorder.h
35,48 → 35,47
#ifndef LIBC_BYTEORDER_H_
#define LIBC_BYTEORDER_H_
 
#include <libarch/byteorder.h>
#include <stdint.h>
 
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN))
#error The architecture must be either big-endian or little-endian.
#if !(defined(__BE__) ^ defined(__LE__))
#error The architecture must be either big-endian or little-endian.
#endif
 
#ifdef ARCH_IS_BIG_ENDIAN
#ifdef __BE__
 
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n)
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n)
#define uint16_t_le2host(n) (uint16_t_byteorder_swap(n))
#define uint32_t_le2host(n) (uint32_t_byteorder_swap(n))
#define uint64_t_le2host(n) (uint64_t_byteorder_swap(n))
 
#define uint16_t_be2host(n) (n)
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
#define uint16_t_be2host(n) (n)
#define uint32_t_be2host(n) (n)
#define uint64_t_be2host(n) (n)
 
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n)
#define host2uint16_t_le(n) (uint16_t_byteorder_swap(n))
#define host2uint32_t_le(n) (uint32_t_byteorder_swap(n))
#define host2uint64_t_le(n) (uint64_t_byteorder_swap(n))
 
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
#define host2uint16_t_be(n) (n)
#define host2uint32_t_be(n) (n)
#define host2uint64_t_be(n) (n)
 
#else
 
#define uint16_t_le2host(n) (n)
#define uint32_t_le2host(n) (n)
#define uint64_t_le2host(n) (n)
#define uint16_t_le2host(n) (n)
#define uint32_t_le2host(n) (n)
#define uint64_t_le2host(n) (n)
 
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n)
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n)
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n)
#define uint16_t_be2host(n) (uint16_t_byteorder_swap(n))
#define uint32_t_be2host(n) (uint32_t_byteorder_swap(n))
#define uint64_t_be2host(n) (uint64_t_byteorder_swap(n))
 
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
#define host2uint16_t_le(n) (n)
#define host2uint32_t_le(n) (n)
#define host2uint64_t_le(n) (n)
 
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n)
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n)
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n)
#define host2uint16_t_be(n) (uint16_t_byteorder_swap(n))
#define host2uint32_t_be(n) (uint32_t_byteorder_swap(n))
#define host2uint64_t_be(n) (uint64_t_byteorder_swap(n))
 
#endif
 
/branches/dynload/uspace/lib/libc/include/getopt.h
58,7 → 58,7
};
 
/* HelenOS Port - These need to be exposed for legacy getopt() */
extern char *optarg;
extern const char *optarg;
extern int optind, opterr, optopt;
extern int optreset;
 
/branches/dynload/uspace/lib/libc/include/fcntl.h
35,13 → 35,13
#ifndef LIBC_FCNTL_H_
#define LIBC_FCNTL_H_
 
#define O_CREAT 1
#define O_EXCL 2
#define O_TRUNC 4
#define O_APPEND 8
#define O_RDONLY 16
#define O_RDWR 32
#define O_WRONLY 64
#define O_CREAT 1
#define O_EXCL 2
#define O_TRUNC 4
#define O_APPEND 8
#define O_RDONLY 16
#define O_RDWR 32
#define O_WRONLY 64
 
extern int open(const char *, int, ...);
 
/branches/dynload/uspace/lib/libc/include/string.h
39,8 → 39,7
#include <sys/types.h>
#include <bool.h>
 
#define U_SPECIAL '?'
#define U_BOM 0xfeff
#define U_SPECIAL '?'
 
/** No size limit constant */
#define STR_NO_LIMIT ((size_t) -1)
54,20 → 53,20
extern size_t str_size(const char *str);
extern size_t wstr_size(const wchar_t *str);
 
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 str_lsize(const char *str, size_t max_len);
extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
 
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
extern size_t str_length(const char *str);
extern size_t wstr_length(const wchar_t *wstr);
 
extern count_t str_nlength(const char *str, size_t size);
extern count_t wstr_nlength(const wchar_t *str, size_t size);
extern size_t str_nlength(const char *str, size_t size);
extern size_t wstr_nlength(const wchar_t *str, size_t size);
 
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 int str_lcmp(const char *s1, const char *s2, size_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);
75,11 → 74,11
 
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 char *str_chr(const char *str, wchar_t ch);
extern 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 bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
extern bool wstr_remove(wchar_t *str, size_t pos);
 
extern char *str_dup(const char *);
 
/branches/dynload/uspace/lib/libc/include/malloc.h
1,537 → 1,51
/*
Default header file for malloc-2.8.x, written by Doug Lea
and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain.
last update: Mon Aug 15 08:55:52 2005 Doug Lea (dl at gee)
* 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.
*/
 
This header is for ANSI C/C++ only. You can set any of
the following #defines before including:
 
* If USE_DL_PREFIX is defined, it is assumed that malloc.c
was also compiled with this option, so all routines
have names starting with "dl".
 
* If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this
file will be #included AFTER <malloc.h>. This is needed only if
your system defines a struct mallinfo that is incompatible with the
standard one declared here. Otherwise, you can include this file
INSTEAD of your system system <malloc.h>. At least on ANSI, all
declarations should be compatible with system versions
 
* If MSPACES is defined, declarations for mspace versions are included.
*/
 
#ifndef MALLOC_280_H
#define MALLOC_280_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include <stddef.h> /* for size_t */
 
#if !ONLY_MSPACES
 
#ifndef USE_DL_PREFIX
#define dlcalloc calloc
#define dlfree free
#define dlmalloc malloc
#define dlmemalign memalign
#define dlrealloc realloc
#define dlvalloc valloc
#define dlpvalloc pvalloc
#define dlmallinfo mallinfo
#define dlmallopt mallopt
#define dlmalloc_trim malloc_trim
#define dlmalloc_stats malloc_stats
#define dlmalloc_usable_size malloc_usable_size
#define dlmalloc_footprint malloc_footprint
#define dlmalloc_max_footprint malloc_max_footprint
#define dlindependent_calloc independent_calloc
#define dlindependent_comalloc independent_comalloc
#endif /* USE_DL_PREFIX */
 
 
/*
malloc(size_t n)
Returns a pointer to a newly allocated chunk of at least n bytes, or
null if no space is available, in which case errno is set to ENOMEM
on ANSI C systems.
 
If n is zero, malloc returns a minimum-sized chunk. (The minimum
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
systems.) Note that size_t is an unsigned type, so calls with
arguments that would be negative if signed are interpreted as
requests for huge amounts of space, which will often fail. The
maximum supported value of n differs across systems, but is in all
cases less than the maximum representable value of a size_t.
*/
void* dlmalloc(size_t);
 
/*
free(void* p)
Releases the chunk of memory pointed to by p, that had been previously
allocated using malloc or a related routine such as realloc.
It has no effect if p is null. If p was not malloced or already
freed, free(p) will by default cuase the current program to abort.
*/
void dlfree(void*);
 
/*
calloc(size_t n_elements, size_t element_size);
Returns a pointer to n_elements * element_size bytes, with all locations
set to zero.
*/
void* dlcalloc(size_t, size_t);
 
/*
realloc(void* p, size_t n)
Returns a pointer to a chunk of size n that contains the same data
as does chunk p up to the minimum of (n, p's size) bytes, or null
if no space is available.
 
The returned pointer may or may not be the same as p. The algorithm
prefers extending p in most cases when possible, otherwise it
employs the equivalent of a malloc-copy-free sequence.
 
If p is null, realloc is equivalent to malloc.
 
If space is not available, realloc returns null, errno is set (if on
ANSI) and p is NOT freed.
 
if n is for fewer bytes than already held by p, the newly unused
space is lopped off and freed if possible. realloc with a size
argument of zero (re)allocates a minimum-sized chunk.
 
The old unix realloc convention of allowing the last-free'd chunk
to be used as an argument to realloc is not supported.
*/
 
void* dlrealloc(void*, size_t);
 
/*
memalign(size_t alignment, size_t n);
Returns a pointer to a newly allocated chunk of n bytes, aligned
in accord with the alignment argument.
 
The alignment argument should be a power of two. If the argument is
not a power of two, the nearest greater power is used.
8-byte alignment is guaranteed by normal malloc calls, so don't
bother calling memalign with an argument of 8 or less.
 
Overreliance on memalign is a sure way to fragment space.
*/
void* dlmemalign(size_t, size_t);
 
/*
valloc(size_t n);
Equivalent to memalign(pagesize, n), where pagesize is the page
size of the system. If the pagesize is unknown, 4096 is used.
*/
void* dlvalloc(size_t);
 
/*
mallopt(int parameter_number, int parameter_value)
Sets tunable parameters The format is to provide a
(parameter-number, parameter-value) pair. mallopt then sets the
corresponding parameter to the argument value if it can (i.e., so
long as the value is meaningful), and returns 1 if successful else
0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
normally defined in malloc.h. None of these are use in this malloc,
so setting them has no effect. But this malloc also supports other
options in mallopt:
 
Symbol param # default allowed param values
M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming)
M_GRANULARITY -2 page size any power of 2 >= page size
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
*/
int dlmallopt(int, int);
 
#define M_TRIM_THRESHOLD (-1)
#define M_GRANULARITY (-2)
#define M_MMAP_THRESHOLD (-3)
 
 
/*
malloc_footprint();
Returns the number of bytes obtained from the system. The total
number of bytes allocated by malloc, realloc etc., is less than this
value. Unlike mallinfo, this function returns only a precomputed
result, so can be called frequently to monitor memory consumption.
Even if locks are otherwise defined, this function does not use them,
so results might not be up to date.
*/
size_t dlmalloc_footprint(void);
size_t dlmalloc_max_footprint(void);
 
#if !NO_MALLINFO
/*
mallinfo()
Returns (by copy) a struct containing various summary statistics:
 
arena: current total non-mmapped bytes allocated from system
ordblks: the number of free chunks
smblks: always zero.
hblks: current number of mmapped regions
hblkhd: total bytes held in mmapped regions
usmblks: the maximum total allocated space. This will be greater
than current total if trimming has occurred.
fsmblks: always zero
uordblks: current total allocated space (normal or mmapped)
fordblks: total free space
keepcost: the maximum number of bytes that could ideally be released
back to system via malloc_trim. ("ideally" means that
it ignores page restrictions etc.)
 
Because these fields are ints, but internal bookkeeping may
be kept as longs, the reported values may wrap around zero and
thus be inaccurate.
*/
#ifndef HAVE_USR_INCLUDE_MALLOC_H
#ifndef _MALLOC_H
#ifndef MALLINFO_FIELD_TYPE
#define MALLINFO_FIELD_TYPE size_t
#endif /* MALLINFO_FIELD_TYPE */
struct mallinfo {
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
MALLINFO_FIELD_TYPE smblks; /* always 0 */
MALLINFO_FIELD_TYPE hblks; /* always 0 */
MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
MALLINFO_FIELD_TYPE fordblks; /* total free space */
MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
};
#endif /* _MALLOC_H */
#endif /* HAVE_USR_INCLUDE_MALLOC_H */
 
struct mallinfo dlmallinfo(void);
#endif /* NO_MALLINFO */
 
/*
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
 
independent_calloc is similar to calloc, but instead of returning a
single cleared space, it returns an array of pointers to n_elements
independent elements that can hold contents of size elem_size, each
of which starts out cleared, and can be independently freed,
realloc'ed etc. The elements are guaranteed to be adjacently
allocated (this is not guaranteed to occur with multiple callocs or
mallocs), which may also improve cache locality in some
applications.
 
The "chunks" argument is optional (i.e., may be null, which is
probably the most typical usage). If it is null, the returned array
is itself dynamically allocated and should also be freed when it is
no longer needed. Otherwise, the chunks array must be of at least
n_elements in length. It is filled in with the pointers to the
chunks.
 
In either case, independent_calloc returns this pointer array, or
null if the allocation failed. If n_elements is zero and "chunks"
is null, it returns a chunk representing an array with zero elements
(which should be freed if not wanted).
 
Each element must be individually freed when it is no longer
needed. If you'd like to instead be able to free all at once, you
should instead use regular calloc and assign pointers into this
space to represent elements. (In this case though, you cannot
independently free elements.)
 
independent_calloc simplifies and speeds up implementations of many
kinds of pools. It may also be useful when constructing large data
structures that initially have a fixed number of fixed-sized nodes,
but the number is not known at compile time, and some of the nodes
may later need to be freed. For example:
 
struct Node { int item; struct Node* next; };
 
struct Node* build_list() {
struct Node** pool;
int n = read_number_of_nodes_needed();
if (n <= 0) return 0;
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
if (pool == 0) die();
// organize into a linked list...
struct Node* first = pool[0];
for (i = 0; i < n-1; ++i)
pool[i]->next = pool[i+1];
free(pool); // Can now free the array (or not, if it is needed later)
return first;
}
*/
void** dlindependent_calloc(size_t, size_t, void**);
 
/*
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
 
independent_comalloc allocates, all at once, a set of n_elements
chunks with sizes indicated in the "sizes" array. It returns
an array of pointers to these elements, each of which can be
independently freed, realloc'ed etc. The elements are guaranteed to
be adjacently allocated (this is not guaranteed to occur with
multiple callocs or mallocs), which may also improve cache locality
in some applications.
 
The "chunks" argument is optional (i.e., may be null). If it is null
the returned array is itself dynamically allocated and should also
be freed when it is no longer needed. Otherwise, the chunks array
must be of at least n_elements in length. It is filled in with the
pointers to the chunks.
 
In either case, independent_comalloc returns this pointer array, or
null if the allocation failed. If n_elements is zero and chunks is
null, it returns a chunk representing an array with zero elements
(which should be freed if not wanted).
 
Each element must be individually freed when it is no longer
needed. If you'd like to instead be able to free all at once, you
should instead use a single regular malloc, and assign pointers at
particular offsets in the aggregate space. (In this case though, you
cannot independently free elements.)
 
independent_comallac differs from independent_calloc in that each
element may have a different size, and also that it does not
automatically clear elements.
 
independent_comalloc can be used to speed up allocation in cases
where several structs or objects must always be allocated at the
same time. For example:
 
struct Head { ... }
struct Foot { ... }
 
void send_message(char* msg) {
int msglen = strlen(msg);
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
void* chunks[3];
if (independent_comalloc(3, sizes, chunks) == 0)
die();
struct Head* head = (struct Head*)(chunks[0]);
char* body = (char*)(chunks[1]);
struct Foot* foot = (struct Foot*)(chunks[2]);
// ...
}
 
In general though, independent_comalloc is worth using only for
larger values of n_elements. For small values, you probably won't
detect enough difference from series of malloc calls to bother.
 
Overuse of independent_comalloc can increase overall memory usage,
since it cannot reuse existing noncontiguous small chunks that
might be available for some of the elements.
*/
void** dlindependent_comalloc(size_t, size_t*, void**);
 
 
/*
pvalloc(size_t n);
Equivalent to valloc(minimum-page-that-holds(n)), that is,
round up n to nearest pagesize.
/** @addtogroup libc
* @{
*/
void* dlpvalloc(size_t);
/** @file
*/
 
/*
malloc_trim(size_t pad);
#ifndef LIBC_MALLOC_H_
#define LIBC_MALLOC_H_
 
If possible, gives memory back to the system (via negative arguments
to sbrk) if there is unused memory at the `high' end of the malloc
pool or in unused MMAP segments. You can call this after freeing
large blocks of memory to potentially reduce the system-level memory
requirements of a program. However, it cannot guarantee to reduce
memory. Under some allocation patterns, some large free blocks of
memory will be locked between two used chunks, so they cannot be
given back to the system.
#include <sys/types.h>
 
The `pad' argument to malloc_trim represents the amount of free
trailing space to leave untrimmed. If this argument is zero, only
the minimum amount of memory to maintain internal data structures
will be left. Non-zero arguments can be supplied to maintain enough
trailing space to service future expected allocations without having
to re-obtain memory from the system.
extern void __heap_init(void);
extern uintptr_t get_max_heap_addr(void);
 
Malloc_trim returns 1 if it actually released any memory, else 0.
*/
int dlmalloc_trim(size_t);
extern void *malloc(const size_t size);
extern void *memalign(const size_t align, const size_t size);
extern void *realloc(const void *addr, const size_t size);
extern void free(const void *addr);
 
/*
malloc_usable_size(void* p);
 
Returns the number of bytes you can actually use in
an allocated chunk, which may be more than you requested (although
often not) due to alignment and minimum size constraints.
You can use this many bytes without worrying about
overwriting other allocated objects. This is not a particularly great
programming practice. malloc_usable_size can be more useful in
debugging and assertions, for example:
 
p = malloc(n);
assert(malloc_usable_size(p) >= 256);
*/
size_t dlmalloc_usable_size(void*);
 
/*
malloc_stats();
Prints on stderr the amount of space obtained from the system (both
via sbrk and mmap), the maximum amount (which may be more than
current if malloc_trim and/or munmap got called), and the current
number of bytes allocated via malloc (or realloc, etc) but not yet
freed. Note that this is the number of bytes allocated, not the
number requested. It will be larger than the number requested
because of alignment and bookkeeping overhead. Because it includes
alignment wastage as being in use, this figure may be greater than
zero even when no user-level chunks are allocated.
 
The reported current and maximum system memory can be inaccurate if
a program makes other calls to system memory allocation functions
(normally sbrk) outside of malloc.
 
malloc_stats prints only the most commonly interesting statistics.
More information can be obtained by calling mallinfo.
*/
void dlmalloc_stats(void);
 
#endif /* !ONLY_MSPACES */
 
#if MSPACES
 
/*
mspace is an opaque type representing an independent
region of space that supports mspace_malloc, etc.
*/
typedef void* mspace;
 
/*
create_mspace creates and returns a new independent space with the
given initial capacity, or, if 0, the default granularity size. It
returns null if there is no system memory available to create the
space. If argument locked is non-zero, the space uses a separate
lock to control access. The capacity of the space will grow
dynamically as needed to service mspace_malloc requests. You can
control the sizes of incremental increases of this space by
compiling with a different DEFAULT_GRANULARITY or dynamically
setting with mallopt(M_GRANULARITY, value).
*/
mspace create_mspace(size_t capacity, int locked);
 
/*
destroy_mspace destroys the given space, and attempts to return all
of its memory back to the system, returning the total number of
bytes freed. After destruction, the results of access to all memory
used by the space become undefined.
*/
size_t destroy_mspace(mspace msp);
 
/*
create_mspace_with_base uses the memory supplied as the initial base
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
space is used for bookkeeping, so the capacity must be at least this
large. (Otherwise 0 is returned.) When this initial space is
exhausted, additional memory will be obtained from the system.
Destroying this space will deallocate all additionally allocated
space (if possible) but not the initial base.
*/
mspace create_mspace_with_base(void* base, size_t capacity, int locked);
 
/*
mspace_malloc behaves as malloc, but operates within
the given space.
*/
void* mspace_malloc(mspace msp, size_t bytes);
 
/*
mspace_free behaves as free, but operates within
the given space.
 
If compiled with FOOTERS==1, mspace_free is not actually needed.
free may be called instead of mspace_free because freed chunks from
any space are handled by their originating spaces.
*/
void mspace_free(mspace msp, void* mem);
 
/*
mspace_realloc behaves as realloc, but operates within
the given space.
 
If compiled with FOOTERS==1, mspace_realloc is not actually
needed. realloc may be called instead of mspace_realloc because
realloced chunks from any space are handled by their originating
spaces.
*/
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
 
/*
mspace_calloc behaves as calloc, but operates within
the given space.
*/
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
 
/*
mspace_memalign behaves as memalign, but operates within
the given space.
*/
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
 
/*
mspace_independent_calloc behaves as independent_calloc, but
operates within the given space.
*/
void** mspace_independent_calloc(mspace msp, size_t n_elements,
size_t elem_size, void* chunks[]);
 
/*
mspace_independent_comalloc behaves as independent_comalloc, but
operates within the given space.
*/
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
size_t sizes[], void* chunks[]);
 
/*
mspace_footprint() returns the number of bytes obtained from the
system for this space.
*/
size_t mspace_footprint(mspace msp);
 
 
#if !NO_MALLINFO
/*
mspace_mallinfo behaves as mallinfo, but reports properties of
the given space.
*/
struct mallinfo mspace_mallinfo(mspace msp);
#endif /* NO_MALLINFO */
 
/*
mspace_malloc_stats behaves as malloc_stats, but reports
properties of the given space.
*/
void mspace_malloc_stats(mspace msp);
 
/*
mspace_trim behaves as malloc_trim, but
operates within the given space.
*/
int mspace_trim(mspace msp, size_t pad);
 
/*
An alias for mallopt.
*/
int mspace_mallopt(int, int);
 
#endif /* MSPACES */
 
#ifdef __cplusplus
}; /* end of extern "C" */
#endif
 
#endif /* MALLOC_280_H */
 
 
/** @}
/** @}
*/
/branches/dynload/uspace/lib/libc/include/vfs/vfs.h
36,12 → 36,36
#define LIBC_VFS_H_
 
#include <sys/types.h>
#include <ipc/vfs.h>
#include <ipc/devmap.h>
#include <stdio.h>
 
/**
* This type is a libc version of the VFS triplet.
* It uniquelly identifies a file system node within a file system instance.
*/
typedef struct {
fs_handle_t fs_handle;
dev_handle_t dev_handle;
fs_index_t index;
} fdi_node_t;
 
extern char *absolutize(const char *, size_t *);
 
extern int mount(const char *, const char *, const char *, const char *,
const unsigned int flags);
unsigned int);
 
extern void __stdio_init(int filc, fdi_node_t *filv[]);
extern void __stdio_done(void);
 
extern int open_node(fdi_node_t *, int);
extern int fd_phone(int);
extern int fd_node(int, fdi_node_t *);
 
extern FILE *fopen_node(fdi_node_t *, const char *);
extern int fphone(FILE *);
extern int fnode(FILE *, fdi_node_t *);
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/async.h
44,17 → 44,21
typedef ipc_callid_t aid_t;
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
 
static inline void async_manager(void)
{
fibril_switch(FIBRIL_TO_MANAGER);
}
extern atomic_t async_futex;
 
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
extern int __async_init(void);
extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
 
static inline ipc_callid_t async_get_call(ipc_call_t *data)
{
return async_get_call_timeout(data, 0);
}
 
static inline void async_manager(void)
{
fibril_switch(FIBRIL_TO_MANAGER);
}
 
/*
* User-friendly wrappers for async_send_fast() and async_send_slow(). The
* macros are in the form async_send_m(), where m denotes the number of payload
63,19 → 67,19
*/
 
#define async_send_0(phoneid, method, dataptr) \
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
#define async_send_1(phoneid, method, arg1, dataptr) \
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
#define async_send_2(phoneid, method, arg1, arg2, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
#define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
#define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(dataptr))
async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(dataptr))
#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
async_send_slow((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);
86,12 → 90,11
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,
extern 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);
int _async_init(void);
extern void async_usleep(suseconds_t timeout);
extern void async_create_manager(void);
extern void async_destroy_manager(void);
 
extern void async_set_client_connection(async_client_conn_t conn);
extern void async_set_interrupt_received(async_client_conn_t conn);
98,22 → 101,22
 
/* Wrappers for simple communication */
#define async_msg_0(phone, method) \
ipc_call_async_0((phone), (method), NULL, NULL, true)
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, \
true)
ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
true)
#define async_msg_2(phone, method, arg1, arg2) \
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
true)
ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
true)
#define async_msg_3(phone, method, arg1, arg2, arg3) \
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
true)
ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
true)
#define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, true)
ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
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, true)
ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, true)
 
/*
* User-friendly wrappers for async_req_fast() and async_req_slow(). The macros
122,90 → 125,90
* and slow verion based on m.
*/
#define async_req_0_0(phoneid, method) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
NULL)
#define async_req_0_1(phoneid, method, r1) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
NULL)
#define async_req_0_2(phoneid, method, r1, r2) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
NULL)
#define async_req_0_3(phoneid, method, r1, r2, r3) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
NULL)
#define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
NULL)
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
NULL)
#define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
(r5))
async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
(r5))
#define async_req_1_0(phoneid, method, arg1) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL)
#define async_req_1_1(phoneid, method, arg1, rc1) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
NULL, NULL)
#define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
NULL, NULL)
#define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
NULL, NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
NULL, NULL)
#define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), NULL)
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), NULL)
#define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), (rc5))
async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
(rc4), (rc5))
#define async_req_2_0(phoneid, method, arg1, arg2) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
NULL, NULL, NULL)
#define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
NULL, NULL, NULL)
#define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
NULL, NULL, NULL)
#define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), NULL, NULL)
#define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), NULL)
#define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), (rc5))
async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
(rc3), (rc4), (rc5))
#define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
NULL, NULL, NULL)
#define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
NULL, NULL, NULL, NULL)
#define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), NULL, NULL, NULL)
#define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), NULL, NULL)
#define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), NULL)
#define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
rc5) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
(rc2), (rc3), (rc4), (rc5))
#define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
NULL, NULL, NULL, NULL)
#define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
NULL, NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
NULL, NULL, NULL, NULL)
#define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), NULL, NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), NULL, NULL, NULL)
#define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), (rc3), NULL, NULL)
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
(rc2), (rc3), NULL, NULL)
#define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
rc4) \
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
215,14 → 218,14
async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(rc1), (rc2), (rc3), (rc4), (rc5))
#define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), NULL, NULL, NULL, NULL, NULL)
#define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), NULL, NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), NULL, NULL, NULL, NULL)
#define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), (rc2), NULL, NULL, NULL)
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (rc1), (rc2), NULL, NULL, NULL)
#define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
rc3) \
async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
253,8 → 256,6
fibril_dec_sercount();
}
 
extern atomic_t async_futex;
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/stdlib.h
38,10 → 38,10
#include <unistd.h>
#include <malloc.h>
 
#define abort() _exit(1)
#define exit(status) _exit((status))
#define abort() _exit(1)
#define exit(status) _exit((status))
 
#define RAND_MAX 714025
#define RAND_MAX 714025
 
extern long int random(void);
extern void srandom(unsigned int seed);
50,6 → 50,7
{
return random();
}
 
static inline void srand(unsigned int seed)
{
srandom(seed);
/branches/dynload/uspace/lib/libc/include/stdio.h
37,78 → 37,118
 
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <adt/list.h>
 
#define EOF (-1)
#define EOF (-1)
 
#include <string.h>
#include <io/stream.h>
/** Default size for stream I/O buffers */
#define BUFSIZ 4096
 
#define DEBUG(fmt, ...) \
{ \
char buf[256]; \
int n; \
n = snprintf(buf, sizeof(buf), fmt, ##__VA_ARGS__); \
if (n > 0) \
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, str_size(buf)); \
}
{ \
char _buf[256]; \
int _n = snprintf(_buf, sizeof(_buf), fmt, ##__VA_ARGS__); \
if (_n > 0) \
(void) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) _buf, str_size(_buf)); \
}
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
enum _buffer_type {
/** No buffering */
_IONBF,
/** Line buffering */
_IOLBF,
/** Full buffering */
_IOFBF
};
 
typedef struct {
/** Linked list pointer. */
link_t link;
/** Underlying file descriptor. */
int fd;
 
/** Error indicator. */
int error;
 
/** End-of-file indicator. */
int eof;
/** Klog indicator */
int klog;
/** Phone to the file provider */
int phone;
 
/** Buffering type */
enum _buffer_type btype;
/** Buffer */
uint8_t *buf;
/** Buffer size */
size_t buf_size;
/** Buffer I/O pointer */
uint8_t *buf_head;
} FILE;
 
extern FILE *stdin, *stdout, *stderr;
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
 
/* Character and string input functions */
extern int fgetc(FILE *);
extern char *fgets(char *, size_t, FILE *);
 
extern int getchar(void);
extern char *gets(char *, size_t);
 
/* Character and string output functions */
extern int fputc(wchar_t, FILE *);
extern int fputs(const char *, FILE *);
 
extern int putchar(wchar_t);
extern int puts(const char *);
extern int putchar(int);
extern int fflush(FILE *);
 
/* Formatted string output functions */
extern int fprintf(FILE *, const char*, ...);
extern int vfprintf(FILE *, const char *, va_list);
 
extern int printf(const char *, ...);
extern int vprintf(const char *, va_list);
 
extern int snprintf(char *, size_t , const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int vprintf(const char *, va_list);
extern int vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
extern int rename(const char *, const char *);
 
/* File stream functions */
extern FILE *fopen(const char *, const char *);
extern FILE *fdopen(int, 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 fseek(FILE *, long, int);
extern void rewind(FILE *);
extern int ftell(FILE *);
extern int feof(FILE *);
 
extern int fflush(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 void setvbuf(FILE *, void *, int, size_t);
 
extern int fprintf(FILE *, const char *, ...);
extern int vfprintf(FILE *, const char *, va_list);
/* Misc file functions */
extern int rename(const char *, const char *);
 
#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/dynload/uspace/lib/libc/include/dirent.h
35,7 → 35,7
#ifndef LIBC_DIRENT_H_
#define LIBC_DIRENT_H_
 
#define NAME_MAX 256
#define NAME_MAX 256
 
struct dirent {
char d_name[NAME_MAX + 1];
46,7 → 46,6
struct dirent res;
} DIR;
 
 
extern DIR *opendir(const char *);
extern struct dirent *readdir(DIR *);
extern void rewinddir(DIR *);
/branches/dynload/uspace/lib/libc/include/bitops.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
/** @addtogroup generic
* @{
*/
/** @file
42,10 → 42,10
*
* If number is zero, it returns 0
*/
static inline int fnzb32(uint32_t arg)
static inline unsigned int fnzb32(uint32_t arg)
{
int n = 0;
 
unsigned int n = 0;
if (arg >> 16) {
arg >>= 16;
n += 16;
74,19 → 74,22
return n;
}
 
static inline int fnzb64(uint64_t arg)
static inline unsigned int fnzb64(uint64_t arg)
{
int n = 0;
 
unsigned int n = 0;
if (arg >> 32) {
arg >>= 32;
n += 32;
}
return n + fnzb32((uint32_t) arg);
return (n + fnzb32((uint32_t) arg));
}
 
#define fnzb(x) fnzb32(x)
static inline unsigned int fnzb(size_t arg)
{
return fnzb64(arg);
}
 
#endif
 
/branches/dynload/uspace/lib/libc/include/task.h
39,10 → 39,18
 
typedef uint64_t task_id_t;
 
typedef enum {
TASK_EXIT_NORMAL,
TASK_EXIT_UNEXPECTED
} task_exit_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[]);
extern int task_wait(task_id_t id, task_exit_t *texit, int *retval);
extern int task_retval(int val);
 
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/fibril_sync.h
0,0 → 1,104
/*
* 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_FIBRIL_SYNC_H_
#define LIBC_FIBRIL_SYNC_H_
 
#include <async.h>
#include <fibril.h>
#include <adt/list.h>
#include <libarch/tls.h>
 
typedef struct {
int counter;
link_t waiters;
} fibril_mutex_t;
 
#define FIBRIL_MUTEX_INITIALIZE(name) \
fibril_mutex_t name = { \
.counter = 1, \
.waiters = { \
.prev = &name.waiters, \
.next = &name.waiters, \
} \
}
 
typedef struct {
unsigned writers;
unsigned readers;
link_t waiters;
} fibril_rwlock_t;
 
#define FIBRIL_RWLOCK_INITIALIZE(name) \
fibril_rwlock_t name = { \
.readers = 0, \
.writers = 0, \
.waiters = { \
.prev = &name.waiters, \
.next = &name.waiters, \
} \
}
 
typedef struct {
link_t waiters;
} fibril_condvar_t;
 
#define FIBRIL_CONDVAR_INITIALIZE(name) \
fibril_condvar_t name = { \
.waiters = { \
.next = &name.waiters, \
.prev = &name.waiters, \
} \
}
 
extern void fibril_mutex_initialize(fibril_mutex_t *);
extern void fibril_mutex_lock(fibril_mutex_t *);
extern bool fibril_mutex_trylock(fibril_mutex_t *);
extern void fibril_mutex_unlock(fibril_mutex_t *);
 
extern void fibril_rwlock_initialize(fibril_rwlock_t *);
extern void fibril_rwlock_read_lock(fibril_rwlock_t *);
extern void fibril_rwlock_write_lock(fibril_rwlock_t *);
extern void fibril_rwlock_read_unlock(fibril_rwlock_t *);
extern void fibril_rwlock_write_unlock(fibril_rwlock_t *);
 
extern void fibril_condvar_initialize(fibril_condvar_t *);
extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
extern void fibril_condvar_signal(fibril_condvar_t *);
extern void fibril_condvar_broadcast(fibril_condvar_t *);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/unistd.h
39,29 → 39,32
#include <libarch/config.h>
 
#ifndef NULL
#define NULL 0
#define NULL 0
#endif
 
#define getpagesize() (PAGE_SIZE)
#define getpagesize() (PAGE_SIZE)
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#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);
 
extern off_t lseek(int, off_t, int);
extern int ftruncate(int, off_t);
 
extern int close(int);
extern int fsync(int);
extern int unlink(const char *);
 
extern char *getcwd(char *buf, size_t);
extern int rmdir(const char *);
extern int chdir(const char *);
extern char *getcwd(char *buf, size_t);
 
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/dynload/uspace/lib/libc/include/fibril.h
36,17 → 36,18
#define LIBC_FIBRIL_H_
 
#include <libarch/fibril.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <libarch/tls.h>
 
#ifndef context_set
#define context_set(c, _pc, stack, size, ptls) \
(c)->pc = (sysarg_t) (_pc); \
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
(c)->tls = (sysarg_t) (ptls);
#define context_set(c, _pc, stack, size, ptls) \
(c)->pc = (sysarg_t) (_pc); \
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
(c)->tls = (sysarg_t) (ptls);
#endif /* context_set */
 
#define FIBRIL_SERIALIZED 1
#define FIBRIL_SERIALIZED 1
#define FIBRIL_WRITER 2
 
typedef enum {
FIBRIL_PREEMPT,
71,7 → 72,10
};
typedef struct fibril fibril_t;
 
extern int context_save(context_t *c);
/** Fibril-local variable specifier */
#define fibril_local __thread
 
extern int context_save(context_t *c) __attribute__ ((returns_twice));
extern void context_restore(context_t *c) __attribute__ ((noreturn));
 
extern fid_t fibril_create(int (*func)(void *), void *arg);
/branches/dynload/uspace/lib/libc/include/devmap.h
0,0 → 1,59
/*
* 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_DEVMAP_H_
#define LIBC_DEVMAP_H_
 
#include <ipc/devmap.h>
#include <async.h>
 
extern int devmap_get_phone(devmap_interface_t, unsigned int);
extern void devmap_hangup_phone(devmap_interface_t iface);
 
extern int devmap_driver_register(const char *, async_client_conn_t);
extern int devmap_device_register(const char *, dev_handle_t *);
 
extern int devmap_device_get_handle(const char *, dev_handle_t *, unsigned int);
extern int devmap_device_connect(dev_handle_t, unsigned int);
 
extern int devmap_null_create(void);
extern void devmap_null_destroy(int);
 
extern ipcarg_t devmap_device_get_count(void);
extern ipcarg_t devmap_device_get_devices(ipcarg_t, dev_desc_t *);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/mem.h
39,9 → 39,9
 
#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 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);
 
/branches/dynload/uspace/lib/libc/include/loader/pcb.h
37,6 → 37,7
#define LIBC_PCB_H_
 
#include <sys/types.h>
#include <vfs/vfs.h>
 
typedef void (*entry_point_t)(void);
 
45,19 → 46,26
* Holds pointers to data passed from the program loader to the program
* and/or to the dynamic linker. This includes the program entry point,
* arguments, environment variables etc.
*
*/
typedef struct {
/** Program entry point. */
entry_point_t entry;
 
/** Number of command-line arguments. */
int argc;
/** Command-line arguments. */
char **argv;
 
/** Number of preset files. */
int filc;
/** Preset files. */
fdi_node_t **filv;
/*
* ELF-specific data.
*/
/** Pointer to ELF dynamic section of the program. */
void *dynamic;
/** Pointer to dynamic linker state structure (runtime_env_t). */
/branches/dynload/uspace/lib/libc/include/loader/loader.h
37,6 → 37,7
#define LIBC_LOADER_H_
 
#include <task.h>
#include <vfs/vfs.h>
 
/** Abstraction of a loader connection */
typedef struct {
48,7 → 49,8
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 []);
extern int loader_set_args(loader_t *, char *const[]);
extern int loader_set_files(loader_t *, fdi_node_t *const[]);
extern int loader_load_program(loader_t *);
extern int loader_run(loader_t *);
extern void loader_abort(loader_t *);
/branches/dynload/uspace/lib/libc/include/io/io.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/stream.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/printf_core.h
56,5 → 56,3
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/io/klog.h
0,0 → 1,46
/*
* Copyright (c) 2006 Jakub Vana
* 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_STREAM_H_
#define LIBC_STREAM_H_
 
#include <sys/types.h>
 
extern size_t klog_write(const void *buf, size_t size);
extern void klog_update(void);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/io/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_IO_COLOR_H_
#define LIBC_IO_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/dynload/uspace/lib/libc/include/io/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_IO_STYLE_H_
#define LIBC_IO_STYLE_H_
 
enum console_style {
STYLE_NORMAL = 0,
STYLE_EMPHASIS = 1
};
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/io/console.h
0,0 → 1,86
/*
* 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_IO_CONSOLE_H_
#define LIBC_IO_CONSOLE_H_
 
#include <ipc/ipc.h>
#include <bool.h>
 
typedef enum {
KEY_PRESS,
KEY_RELEASE
} console_ev_type_t;
 
enum {
CONSOLE_CCAP_NONE = 0,
CONSOLE_CCAP_STYLE,
CONSOLE_CCAP_INDEXED,
CONSOLE_CCAP_RGB
};
 
/** Console event structure. */
typedef struct {
/** Press or release event. */
console_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;
} console_event_t;
 
extern void console_clear(int phone);
 
extern int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols);
extern void console_goto(int phone, ipcarg_t row, ipcarg_t col);
 
extern void console_set_style(int phone, int style);
extern void console_set_color(int phone, int fg_color, int bg_color, int flags);
extern void console_set_rgb_color(int phone, int fg_color, int bg_color);
 
extern void console_cursor_visibility(int phone, bool show);
extern int console_get_color_cap(int phone, int *ccap);
extern void console_kcon_enable(int phone);
 
extern bool console_get_event(int phone, console_event_t *event);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/io/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_IO_KEYCODE_H_
#define LIBC_IO_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/dynload/uspace/lib/libc/include/adt/gcdlcm.h
0,0 → 1,73
/*
* 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_GCDLCM_H_
#define LIBC_GCDLCM_H_
 
#include <sys/types.h>
 
#define DECLARE_GCD(type, name) \
static inline type name(type a, type b) \
{ \
if (a == 0) \
return b; \
\
while (b != 0) { \
if (a > b) \
a -= b; \
else \
b -= a; \
} \
\
return a; \
}
 
#define DECLARE_LCM(type, name, gcd) \
static inline type name(type a, type b) \
{ \
return (a * b) / gcd(a, b); \
}
 
DECLARE_GCD(uint32_t, gcd32);
DECLARE_GCD(uint64_t, gcd64);
DECLARE_GCD(size_t, gcd);
 
DECLARE_LCM(uint32_t, lcm32, gcd32);
DECLARE_LCM(uint64_t, lcm64, gcd64);
DECLARE_LCM(size_t, lcm, gcd);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/adt/hash_table.h
0,0 → 1,94
/*
* Copyright (c) 2006 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_HASH_TABLE_H_
#define LIBC_HASH_TABLE_H_
 
#include <adt/list.h>
#include <unistd.h>
 
typedef unsigned long hash_count_t;
typedef unsigned long hash_index_t;
typedef struct hash_table hash_table_t;
typedef struct hash_table_operations hash_table_operations_t;
 
/** Hash table structure. */
struct hash_table {
link_t *entry;
hash_count_t entries;
hash_count_t max_keys;
hash_table_operations_t *op;
};
 
/** Set of operations for hash table. */
struct hash_table_operations {
/** Hash function.
*
* @param key Array of keys needed to compute hash index. All keys
* must be passed.
*
* @return Index into hash table.
*/
hash_index_t (* hash)(unsigned long key[]);
/** Hash table item comparison function.
*
* @param key Array of keys that will be compared with item. It is
* not necessary to pass all keys.
*
* @return true if the keys match, false otherwise.
*/
int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
 
/** Hash table item removal callback.
*
* @param item Item that was removed from the hash table.
*/
void (*remove_callback)(link_t *item);
};
 
#define hash_table_get_instance(item, type, member) \
list_get_instance((item), type, member)
 
extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
hash_table_operations_t *);
extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
extern link_t *hash_table_find(hash_table_t *, unsigned long []);
extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t);
extern void hash_table_destroy(hash_table_t *);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/adt/list.h
0,0 → 1,201
/*
* Copyright (c) 2001-2004 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_LIST_H_
#define LIBC_LIST_H_
 
#include <unistd.h>
 
/** Doubly linked list head and link type. */
typedef struct link {
struct link *prev; /**< Pointer to the previous item in the list. */
struct link *next; /**< Pointer to the next item in the list. */
} link_t;
 
/** Declare and initialize statically allocated list.
*
* @param name Name of the new statically allocated list.
*/
#define LIST_INITIALIZE(name) link_t name = { \
.prev = &name, \
.next = &name \
}
 
/** Initialize doubly-linked circular list link
*
* Initialize doubly-linked list link.
*
* @param link Pointer to link_t structure to be initialized.
*/
static inline void link_initialize(link_t *link)
{
link->prev = NULL;
link->next = NULL;
}
 
/** Initialize doubly-linked circular list
*
* Initialize doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_initialize(link_t *head)
{
head->prev = head;
head->next = head;
}
 
/** Add item to the beginning of doubly-linked circular list
*
* Add item to the beginning of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_prepend(link_t *link, link_t *head)
{
link->next = head->next;
link->prev = head;
head->next->prev = link;
head->next = link;
}
 
/** Add item to the end of doubly-linked circular list
*
* Add item to the end of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_append(link_t *link, link_t *head)
{
link->prev = head->prev;
link->next = head;
head->prev->next = link;
head->prev = link;
}
 
/** Insert item before another item in doubly-linked circular list. */
static inline void list_insert_before(link_t *l, link_t *r)
{
list_append(l, r);
}
 
/** Insert item after another item in doubly-linked circular list. */
static inline void list_insert_after(link_t *r, link_t *l)
{
list_prepend(l, r);
}
 
/** Remove item from doubly-linked circular list
*
* Remove item from doubly-linked circular list.
*
* @param link Pointer to link_t structure to be removed from the list it is contained in.
*/
static inline void list_remove(link_t *link)
{
link->next->prev = link->prev;
link->prev->next = link->next;
link_initialize(link);
}
 
/** Query emptiness of doubly-linked circular list
*
* Query emptiness of doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline int list_empty(link_t *head)
{
return ((head->next == head) ? 1 : 0);
}
 
 
/** Split or concatenate headless doubly-linked circular list
*
* Split or concatenate headless doubly-linked circular list.
*
* Note that the algorithm works both directions:
* concatenates splitted lists and splits concatenated lists.
*
* @param part1 Pointer to link_t structure leading the first (half of the headless) list.
* @param part2 Pointer to link_t structure leading the second (half of the headless) list.
*/
static inline void headless_list_split_or_concat(link_t *part1, link_t *part2)
{
part1->prev->next = part2;
part2->prev->next = part1;
link_t *hlp = part1->prev;
part1->prev = part2->prev;
part2->prev = hlp;
}
 
 
/** Split headless doubly-linked circular list
*
* Split headless doubly-linked circular list.
*
* @param part1 Pointer to link_t structure leading the first half of the headless list.
* @param part2 Pointer to link_t structure leading the second half of the headless list.
*/
static inline void headless_list_split(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
/** Concatenate two headless doubly-linked circular lists
*
* Concatenate two headless doubly-linked circular lists.
*
* @param part1 Pointer to link_t structure leading the first headless list.
* @param part2 Pointer to link_t structure leading the second headless list.
*/
static inline void headless_list_concat(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
#define list_get_instance(link, type, member) ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
 
extern int list_member(const link_t *link, const link_t *head);
extern void list_concat(link_t *head1, link_t *head2);
extern unsigned int list_count(const link_t *link);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/adt/fifo.h
0,0 → 1,127
/*
* Copyright (c) 2006 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
*/
 
/*
* This implementation of FIFO stores values in an array
* (static or dynamic). As such, these FIFOs have upper bound
* on number of values they can store. Push and pop operations
* are done via accessing the array through head and tail indices.
* Because of better operation ordering in fifo_pop(), the access
* policy for these two indices is to 'increment (mod size of FIFO)
* and use'.
*/
 
#ifndef LIBC_FIFO_H_
#define LIBC_FIFO_H_
 
#include <malloc.h>
 
typedef unsigned long fifo_count_t;
typedef unsigned long fifo_index_t;
 
#define FIFO_CREATE_STATIC(name, t, itms) \
struct { \
t fifo[(itms)]; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name
 
/** Create and initialize static FIFO.
*
* FIFO is allocated statically.
* This macro is suitable for creating smaller FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_STATIC(name, t, itms) \
FIFO_CREATE_STATIC(name, t, itms) = { \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Create and prepare dynamic FIFO.
*
* FIFO is allocated dynamically.
* This macro is suitable for creating larger FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \
struct { \
t *fifo; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name = { \
.fifo = NULL, \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Pop value from head of FIFO.
*
* @param name FIFO name.
*
* @return Leading value in FIFO.
*/
#define fifo_pop(name) \
name.fifo[name.head = (name.head + 1) < name.items ? (name.head + 1) : 0]
 
/** Push value to tail of FIFO.
*
* @param name FIFO name.
* @param value Value to be appended to FIFO.
*
*/
#define fifo_push(name, value) \
name.fifo[name.tail = (name.tail + 1) < name.items ? (name.tail + 1) : 0] = (value)
 
/** Allocate memory for dynamic FIFO.
*
* @param name FIFO name.
*/
#define fifo_create(name) \
name.fifo = malloc(sizeof(*name.fifo) * name.items)
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/macros.h
35,15 → 35,25
#ifndef LIBC_MACROS_H_
#define LIBC_MACROS_H_
 
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
 
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
#define LOWER32(arg) ((arg) & 0xffffffff)
#define UPPER32(arg) (((arg) >> 32) & 0xffffffff)
 
#define MERGE_LOUP32(lo, up) \
((((uint64_t) (lo)) & 0xffffffff) \
| ((((uint64_t) (up)) & 0xffffffff) << 32))
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/ipc/ipc.h
30,21 → 30,26
* @{
*/
/** @file
*/
*/
 
#ifndef LIBIPC_IPC_H_
#define LIBIPC_IPC_H_
 
#include <task.h>
#include <kernel/ipc/ipc.h>
#include <kernel/ddi/irq.h>
#include <sys/types.h>
#include <kernel/synch/synch.h>
 
#define IPC_FLAG_BLOCKING 0x01
 
typedef sysarg_t ipcarg_t;
 
typedef struct {
ipcarg_t args[IPC_CALL_LEN];
ipcarg_t in_phone_hash;
} ipc_call_t;
 
typedef sysarg_t ipc_callid_t;
 
typedef void (* ipc_async_callback_t)(void *, int, ipc_call_t *);
56,49 → 61,51
* possible, the fast version is used.
*/
#define ipc_call_sync_0_0(phoneid, method) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
#define ipc_call_sync_0_1(phoneid, method, res1) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
#define ipc_call_sync_0_2(phoneid, method, res1, res2) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
#define ipc_call_sync_0_3(phoneid, method, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
0, 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
0, 0)
#define ipc_call_sync_0_4(phoneid, method, res1, res2, res3, res4) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), 0)
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), 0)
#define ipc_call_sync_0_5(phoneid, method, res1, res2, res3, res4, res5) \
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), (res5))
ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
(res4), (res5))
 
#define ipc_call_sync_1_0(phoneid, method, arg1) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
#define ipc_call_sync_1_1(phoneid, method, arg1, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
#define ipc_call_sync_1_2(phoneid, method, arg1, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
0, 0)
#define ipc_call_sync_1_3(phoneid, method, arg1, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), 0, 0)
#define ipc_call_sync_1_4(phoneid, method, arg1, res1, res2, res3, res4) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), 0)
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), 0)
#define ipc_call_sync_1_5(phoneid, method, arg1, res1, res2, res3, res4, \
res5) \
ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
(res3), (res4), (res5))
 
#define ipc_call_sync_2_0(phoneid, method, arg1, arg2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
0, 0)
#define ipc_call_sync_2_1(phoneid, method, arg1, arg2, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
0, 0)
#define ipc_call_sync_2_2(phoneid, method, arg1, arg2, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), 0, 0, 0)
#define ipc_call_sync_2_3(phoneid, method, arg1, arg2, res1, res2, res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), 0, 0)
#define ipc_call_sync_2_4(phoneid, method, arg1, arg2, res1, res2, res3, \
res4) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
107,15 → 114,16
res4, res5)\
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
(res2), (res3), (res4), (res5))
 
#define ipc_call_sync_3_0(phoneid, method, arg1, arg2, arg3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
0, 0)
#define ipc_call_sync_3_1(phoneid, method, arg1, arg2, arg3, res1) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
0, 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
0, 0, 0, 0)
#define ipc_call_sync_3_2(phoneid, method, arg1, arg2, arg3, res1, res2) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
(res2), 0, 0, 0)
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
(res2), 0, 0, 0)
#define ipc_call_sync_3_3(phoneid, method, arg1, arg2, arg3, res1, res2, \
res3) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
128,15 → 136,16
res3, res4, res5) \
ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
(res1), (res2), (res3), (res4), (res5))
 
#define ipc_call_sync_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
0, 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
0, 0, 0, 0, 0)
#define ipc_call_sync_4_1(phoneid, method, arg1, arg2, arg3, arg4, res1) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), 0, 0, 0, 0)
#define ipc_call_sync_4_2(phoneid, method, arg1, arg2, arg3, arg4, res1, res2) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), (res2), 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
(res1), (res2), 0, 0, 0)
#define ipc_call_sync_4_3(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \
res3) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
149,12 → 158,13
res3, res4, res5) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
(arg4), 0, (res1), (res2), (res3), (res4), (res5))
 
#define ipc_call_sync_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), 0, 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), 0, 0, 0, 0, 0)
#define ipc_call_sync_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (res1), 0, 0, 0, 0)
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
(arg5), (res1), 0, 0, 0, 0)
#define ipc_call_sync_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
res2) \
ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
181,10 → 191,12
 
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 *);
 
/*
194,17 → 206,17
* to m.
*/
#define ipc_answer_0(callid, retval) \
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
ipc_answer_fast((callid), (retval), 0, 0, 0, 0)
#define ipc_answer_1(callid, retval, arg1) \
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
ipc_answer_fast((callid), (retval), (arg1), 0, 0, 0)
#define ipc_answer_2(callid, retval, arg1, arg2) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
ipc_answer_fast((callid), (retval), (arg1), (arg2), 0, 0)
#define ipc_answer_3(callid, retval, arg1, arg2, arg3) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), 0)
#define ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4) \
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
ipc_answer_fast((callid), (retval), (arg1), (arg2), (arg3), (arg4))
#define ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5) \
ipc_answer_slow((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, ipcarg_t, ipcarg_t, ipcarg_t,
ipcarg_t, ipcarg_t);
246,8 → 258,6
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);
 
#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);
256,20 → 266,19
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);
ipcarg_t, ipcarg_t, ipcarg_t, int);
 
 
/*
* User-friendly wrappers for ipc_share_in_start().
*/
#define ipc_share_in_start_0_0(phoneid, dst, size) \
ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
#define ipc_share_in_start_0_1(phoneid, dst, size, flags) \
ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
#define ipc_share_in_start_1_0(phoneid, dst, size, arg) \
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
 
extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *);
extern int ipc_share_in_receive(ipc_callid_t *, size_t *);
284,8 → 293,6
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);
 
#endif
/branches/dynload/uspace/lib/libc/include/ipc/devmap.h
28,16 → 28,19
 
/** @addtogroup devmap
* @{
*/
*/
 
#ifndef DEVMAP_DEVMAP_H_
#define DEVMAP_DEVMAP_H_
 
#include <atomic.h>
#include <ipc/ipc.h>
#include <libadt/list.h>
#include <adt/list.h>
 
#define DEVMAP_NAME_MAXLEN 512
#define DEVMAP_NAME_MAXLEN 255
 
typedef ipcarg_t dev_handle_t;
 
typedef enum {
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
DEVMAP_DRIVER_UNREGISTER,
44,56 → 47,32
DEVMAP_DEVICE_REGISTER,
DEVMAP_DEVICE_UNREGISTER,
DEVMAP_DEVICE_GET_NAME,
DEVMAP_DEVICE_GET_HANDLE
DEVMAP_DEVICE_GET_HANDLE,
DEVMAP_DEVICE_NULL_CREATE,
DEVMAP_DEVICE_NULL_DESTROY,
DEVMAP_DEVICE_GET_COUNT,
DEVMAP_DEVICE_GET_DEVICES
} devmap_request_t;
 
/** Representation of device driver.
* Each driver is responsible for a set of devices.
*/
typedef struct {
/** Pointers to previous and next drivers in linked list */
link_t drivers;
/** Pointer to the linked list of devices controlled by
* this driver */
link_t devices;
/** Phone asociated with this driver */
ipcarg_t phone;
/** Device driver name */
char *name;
/** Futex for list of devices owned by this driver */
atomic_t devices_futex;
} devmap_driver_t;
 
/** Info about registered device
/** Interface provided by devmap.
*
*/
typedef struct {
/** Pointer to the previous and next device in the list of all devices */
link_t devices;
/** Pointer to the previous and next device in the list of devices
owned by one driver */
link_t driver_devices;
/** Unique device identifier */
int handle;
/** Device name */
char *name;
/** Device driver handling this device */
devmap_driver_t *driver;
} devmap_device_t;
 
/** Interface provided by devmap.
* Every process that connects to devmap must ask one of following
* interfaces otherwise connection will be refused.
*
*/
typedef enum {
/** Connect as device driver */
DEVMAP_DRIVER = 1,
/** Connect as client */
/** Connect as device driver */
DEVMAP_DRIVER = 1,
/** Connect as client */
DEVMAP_CLIENT,
/** Create new connection to instance of device that
* is specified by second argument of call. */
/** Create new connection to instance of device that
is specified by second argument of call. */
DEVMAP_CONNECT_TO_DEVICE
} devmap_interface_t;
 
typedef struct {
dev_handle_t handle;
char name[DEVMAP_NAME_MAXLEN + 1];
} dev_desc_t;
 
#endif
 
/branches/dynload/uspace/lib/libc/include/ipc/vfs.h
0,0 → 1,151
/*
* 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 libcipc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IPC_VFS_H_
#define LIBC_IPC_VFS_H_
 
#include <sys/types.h>
#include <ipc/ipc.h>
 
#define FS_NAME_MAXLEN 20
#define MAX_PATH_LEN (64 * 1024)
#define PLB_SIZE (2 * MAX_PATH_LEN)
 
/* Basic types. */
typedef int16_t fs_handle_t;
typedef uint32_t fs_index_t;
 
/**
* A structure like this is passed to VFS by each individual FS upon its
* registration. It assosiates a human-readable identifier with each
* registered FS.
*/
typedef struct {
/** Unique identifier of the fs. */
char name[FS_NAME_MAXLEN + 1];
} vfs_info_t;
 
typedef enum {
VFS_IN_OPEN = IPC_FIRST_USER_METHOD,
VFS_IN_OPEN_NODE,
VFS_IN_READ,
VFS_IN_WRITE,
VFS_IN_SEEK,
VFS_IN_TRUNCATE,
VFS_IN_FSTAT,
VFS_IN_CLOSE,
VFS_IN_MOUNT,
VFS_IN_UNMOUNT,
VFS_IN_SYNC,
VFS_IN_REGISTER,
VFS_IN_MKDIR,
VFS_IN_UNLINK,
VFS_IN_RENAME,
VFS_IN_STAT
} vfs_in_request_t;
 
typedef enum {
VFS_OUT_OPEN_NODE = IPC_FIRST_USER_METHOD,
VFS_OUT_READ,
VFS_OUT_WRITE,
VFS_OUT_TRUNCATE,
VFS_OUT_CLOSE,
VFS_OUT_MOUNT,
VFS_OUT_MOUNTED,
VFS_OUT_UNMOUNT,
VFS_OUT_SYNC,
VFS_OUT_STAT,
VFS_OUT_LOOKUP,
VFS_OUT_DESTROY,
VFS_OUT_LAST
} vfs_out_request_t;
 
/*
* Lookup flags.
*/
 
/**
* No lookup flags used.
*/
#define L_NONE 0
 
/**
* Lookup will succeed only if the object is a regular file. If L_CREATE is
* specified, an empty file will be created. This flag is mutually exclusive
* with L_DIRECTORY.
*/
#define L_FILE 1
 
/**
* Lookup wil succeed only if the object is a directory. If L_CREATE is
* specified, an empty directory will be created. This flag is mutually
* exclusive with L_FILE.
*/
#define L_DIRECTORY 2
 
/**
* When used with L_CREATE, L_EXCLUSIVE will cause the lookup to fail if the
* object already exists. L_EXCLUSIVE is implied when L_DIRECTORY is used.
*/
#define L_EXCLUSIVE 4
 
/**
* L_CREATE is used for creating both regular files and directories.
*/
#define L_CREATE 8
 
/**
* L_LINK is used for linking to an already existing nodes.
*/
#define L_LINK 16
 
/**
* L_UNLINK is used to remove leaves from the file system namespace. This flag
* cannot be passed directly by the client, but will be set by VFS during
* VFS_UNLINK.
*/
#define L_UNLINK 32
 
/**
* L_OPEN is used to indicate that the lookup operation is a part of VFS_OPEN
* call from the client. This means that the server might allocate some
* resources for the opened file. This flag cannot be passed directly by the
* client.
*/
#define L_OPEN 64
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/ipc/ns.h
35,6 → 35,15
#ifndef LIBIPC_NS_H_
#define LIBIPC_NS_H_
 
#include <ipc/ipc.h>
 
typedef enum {
NS_PING = IPC_FIRST_USER_METHOD,
NS_TASK_WAIT,
NS_ID_INTRO,
NS_RETVAL
} ns_request_t;
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/ipc/console.h
27,7 → 27,7
*/
 
/** @addtogroup libcipc
* @{
* @{
*/
/** @file
*/
36,15 → 36,14
#define LIBC_IPC_CONSOLE_H_
 
#include <ipc/ipc.h>
#include <ipc/vfs.h>
 
typedef enum {
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD,
CONSOLE_PUTCHAR,
CONSOLE_WRITE,
CONSOLE_GET_SIZE = VFS_OUT_LAST,
CONSOLE_GET_COLOR_CAP,
CONSOLE_GET_EVENT,
CONSOLE_GOTO,
CONSOLE_CLEAR,
CONSOLE_GOTO,
CONSOLE_GETSIZE,
CONSOLE_FLUSH,
CONSOLE_SET_STYLE,
CONSOLE_SET_COLOR,
CONSOLE_SET_RGB_COLOR,
53,6 → 52,6
} console_request_t;
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/ipc/bd.h
0,0 → 1,48
/*
* 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 libcipc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IPC_BD_H_
#define LIBC_IPC_BD_H_
 
#include <ipc/ipc.h>
 
typedef enum {
BD_READ_BLOCK = IPC_FIRST_USER_METHOD,
BD_WRITE_BLOCK
} bd_request_t;
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/ipc/loader.h
42,6 → 42,7
LOADER_GET_TASKID,
LOADER_SET_PATHNAME,
LOADER_SET_ARGS,
LOADER_SET_FILES,
LOADER_LOAD,
LOADER_RUN
} loader_request_t;
/branches/dynload/uspace/lib/libc/include/ipc/fb.h
41,6 → 41,7
FB_PUTCHAR = IPC_FIRST_USER_METHOD,
FB_CLEAR,
FB_GET_CSIZE,
FB_GET_COLOR_CAP,
FB_CURSOR_VISIBILITY,
FB_CURSOR_GOTO,
FB_SCROLL,
71,6 → 72,13
FB_SCREEN_RECLAIM
} fb_request_t;
 
enum {
FB_CCAP_NONE = 0,
FB_CCAP_STYLE,
FB_CCAP_INDEXED,
FB_CCAP_RGB
};
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/errno.h
35,24 → 35,26
#ifndef LIBC_ERRNO_H_
#define LIBC_ERRNO_H_
 
/* TODO: support threads/fibrils */
#include <kernel/errno.h>
#include <fibril.h>
 
extern int _errno;
 
#define errno _errno
 
#include <kernel/errno.h>
#define EMFILE (-17)
#define ENAMETOOLONG (-256)
#define EISDIR (-257)
#define ENOTDIR (-258)
#define ENOSPC (-259)
#define EEXIST (-260)
#define ENOTEMPTY (-261)
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
 
#define ENAMETOOLONG (-256)
#define EISDIR (-257)
#define ENOTDIR (-258)
#define ENOSPC (-259)
#define EEXIST (-260)
#define ENOTEMPTY (-261)
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
#define EMLINK (-266)
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/sys/stat.h
36,7 → 36,26
#define LIBC_SYS_STAT_H_
 
#include <sys/types.h>
#include <bool.h>
#include <ipc/vfs.h>
#include <ipc/devmap.h>
 
struct stat {
fs_handle_t fs_handle;
dev_handle_t dev_handle;
fs_index_t index;
unsigned lnkcnt;
bool is_file;
off_t size;
union {
struct {
dev_handle_t device;
} devfs_stat;
};
};
 
extern int fstat(int, struct stat *);
extern int stat(const char *, struct stat *);
extern int mkdir(const char *, mode_t);
 
#endif
/branches/dynload/uspace/lib/libc/rtld/include/module.h
37,7 → 37,7
 
#include <sys/types.h>
#include <dynamic.h>
#include <libadt/list.h>
#include <adt/list.h>
 
typedef struct module {
dyn_info_t dyn;
/branches/dynload/uspace/lib/libc/rtld/include/rtld.h
36,7 → 36,7
#define RTLD_H_
 
#include <sys/types.h>
#include <libadt/list.h>
#include <adt/list.h>
 
#include <dynamic.h>
#include <module.h>
/branches/dynload/uspace/lib/libc/rtld/module.c
38,7 → 38,7
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <loader/pcb.h>
 
#include <rtld.h>
/branches/dynload/uspace/lib/libc/Makefile.toolchain
26,10 → 26,11
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
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
CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
-finput-charset=UTF-8 -fno-builtin -Wall -Wextra -Wno-unused-parameter \
-Wmissing-prototypes -Werror-implicit-function-declaration -nostdlib \
-nostdinc -pipe -g -D__$(ENDIANESS)__
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
 
/branches/dynload/uspace/lib/libc/generic/kbd.c
File deleted
/branches/dynload/uspace/lib/libc/generic/libadt/hash_table.c
File deleted
/branches/dynload/uspace/lib/libc/generic/libadt/list.c
File deleted
/branches/dynload/uspace/lib/libc/generic/console.c
File deleted
/branches/dynload/uspace/lib/libc/generic/ddi.c
127,10 → 127,10
}
#endif
 
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
phys = (void *) 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);
virt = as_get_mappable_page(pages << PAGE_WIDTH);
*use_addr = virt + offset;
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
}
/branches/dynload/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/dynload/uspace/lib/libc/generic/as.c
30,7 → 30,7
* @{
*/
/** @file
*/
*/
 
#include <as.h>
#include <libc.h>
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 && -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 == -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/dynload/uspace/lib/libc/generic/string.c
138,8 → 138,8
* @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.
* 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)
{
243,9 → 243,9
* @return Number of bytes used by the characters.
*
*/
size_t str_lsize(const char *str, count_t max_len)
size_t str_lsize(const char *str, size_t max_len)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (len < max_len) {
271,7 → 271,7
* @return Number of bytes used by the wide characters.
*
*/
size_t wstr_lsize(const wchar_t *str, count_t max_len)
size_t wstr_lsize(const wchar_t *str, size_t max_len)
{
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
}
283,9 → 283,9
* @return Number of characters in string.
*
*/
count_t str_length(const char *str)
size_t str_length(const char *str)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
301,9 → 301,9
* @return Number of characters in @a str.
*
*/
count_t wstr_length(const wchar_t *wstr)
size_t wstr_length(const wchar_t *wstr)
{
count_t len = 0;
size_t len = 0;
while (*wstr++ != 0)
len++;
319,9 → 319,9
* @return Number of characters in string.
*
*/
count_t str_nlength(const char *str, size_t size)
size_t str_nlength(const char *str, size_t size)
{
count_t len = 0;
size_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, size) != 0)
338,11 → 338,11
* @return Number of characters in string.
*
*/
count_t wstr_nlength(const wchar_t *str, size_t size)
size_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;
size_t len = 0;
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
size_t offset = 0;
while ((offset < limit) && (*str++ != 0)) {
len++;
430,7 → 430,7
* 1 if second smaller.
*
*/
int str_lcmp(const char *s1, const char *s2, count_t max_len)
int str_lcmp(const char *s1, const char *s2, size_t max_len)
{
wchar_t c1 = 0;
wchar_t c2 = 0;
438,7 → 438,7
size_t off1 = 0;
size_t off2 = 0;
count_t len = 0;
size_t len = 0;
 
while (true) {
if (len >= max_len)
568,7 → 568,7
return;
wchar_t ch;
count_t src_idx = 0;
size_t src_idx = 0;
size_t dst_off = 0;
while ((ch = src[src_idx++]) != 0) {
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,12 → 611,12
*
* @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;
size_t last = 0;
char *res = NULL;
const char *res = NULL;
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
624,7 → 624,7
last = off;
}
return res;
return (char *) res;
}
 
/** Insert a wide character into a wide string.
641,14 → 641,14
* is out of bounds.
*
*/
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
{
count_t len = wstr_length(str);
size_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
count_t i;
size_t i;
for (i = len; i + 1 > pos; i--)
str[i + 1] = str[i];
669,14 → 669,14
* is out of bounds.
*
*/
bool wstr_remove(wchar_t *str, count_t pos)
bool wstr_remove(wchar_t *str, size_t pos)
{
count_t len = wstr_length(str);
size_t len = wstr_length(str);
if (pos >= len)
return false;
count_t i;
size_t i;
for (i = pos + 1; i <= len; i++)
str[i - 1] = str[i];
/branches/dynload/uspace/lib/libc/generic/loader.c
30,7 → 30,7
* @{
*/
/** @file
*/
*/
 
#include <ipc/ipc.h>
#include <ipc/loader.h>
47,9 → 47,12
/** Connect to a new program loader.
*
* Spawns a new program loader task and returns the connection structure.
* @param name Symbolic name to set on the newly created task.
* @return Pointer to the loader connection structure (should be
* de-allocated using free() after use).
*
* @param name Symbolic name to set on the newly created task.
*
* @return Pointer to the loader connection structure (should be
* deallocated using free() after use).
*
*/
int loader_spawn(const char *name)
{
59,19 → 62,16
 
loader_t *loader_connect(void)
{
loader_t *ldr;
int phone_id;
 
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
if (phone_id < 0)
return NULL;
 
ldr = malloc(sizeof(loader_t));
loader_t *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.
78,27 → 78,26
*
* Retrieves the ID of the new task from the loader.
*
* @param ldr Loader connection structure.
* @param task_id Points to a variable where the ID should be stored.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
* @param task_id Points to a variable where the ID should be stored.
*
* @return Zero on success or negative error code.
*
*/
int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
{
/* Get task ID. */
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
/* Get task ID. */
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
ipcarg_t retval;
async_wait_for(req, &retval);
return (int)retval;
return (int) retval;
}
 
/** Set pathname of the program to load.
107,39 → 106,35
* to the current working directory (it will be absolutized before
* sending to the loader).
*
* @param ldr Loader connection structure.
* @param path Pathname of the program file.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
* @param path Pathname of the program file.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_pathname(loader_t *ldr, const char *path)
{
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
char *pa;
size_t pa_len;
 
pa = absolutize(path, &pa_len);
char *pa = absolutize(path, &pa_len);
if (!pa)
return 0;
 
/* Send program pathname */
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
free(pa);
 
ipcarg_t retval;
async_wait_for(req, &retval);
return (int)retval;
return (int) retval;
}
 
 
/** Set command-line arguments for the program.
*
* Sets the vector of command-line arguments to be passed to the loaded
146,61 → 141,110
* program. By convention, the very first argument is typically the same as
* the command used to execute the program.
*
* @param ldr Loader connection structure.
* @param argv NULL-terminated array of pointers to arguments.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
* @param argv NULL-terminated array of pointers to arguments.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_args(loader_t *ldr, char *const argv[])
{
aid_t req;
ipc_call_t answer;
ipcarg_t rc;
 
char *const *ap;
char *dp;
char *arg_buf;
size_t buffer_size;
 
/*
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
ap = argv;
buffer_size = 0;
char *const *ap = argv;
size_t buffer_size = 0;
while (*ap != NULL) {
buffer_size += str_size(*ap) + 1;
++ap;
ap++;
}
 
arg_buf = malloc(buffer_size);
if (arg_buf == NULL) return ENOMEM;
 
char *arg_buf = malloc(buffer_size);
if (arg_buf == NULL)
return ENOMEM;
/* Now fill the buffer with null-terminated argument strings */
ap = argv;
dp = arg_buf;
 
char *dp = arg_buf;
while (*ap != NULL) {
str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
dp += str_size(*ap) + 1;
 
++ap;
ap++;
}
 
/* Send serialized arguments to the loader */
 
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
async_wait_for(req, &rc);
if (rc != EOK) return rc;
 
if (rc != EOK)
return rc;
/* Free temporary buffer */
free(arg_buf);
return EOK;
}
 
/** Set preset files for the program.
*
* Sets the vector of preset files to be passed to the loaded
* program. By convention, the first three files represent stdin,
* stdout and stderr respectively.
*
* @param ldr Loader connection structure.
* @param files NULL-terminated array of pointers to files.
*
* @return Zero on success or negative error code.
*
*/
int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
{
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
fdi_node_t *const *ap = files;
size_t count = 0;
while (*ap != NULL) {
count++;
ap++;
}
fdi_node_t *files_buf;
files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
if (files_buf == NULL)
return ENOMEM;
/* Fill the buffer */
size_t i;
for (i = 0; i < count; i++)
files_buf[i] = *files[i];
/* Send serialized files to the loader */
ipc_call_t answer;
aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf,
count * sizeof(fdi_node_t));
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
async_wait_for(req, &rc);
if (rc != EOK)
return rc;
/* Free temporary buffer */
free(files_buf);
return EOK;
}
 
209,18 → 253,14
* If this function succeeds, the program has been successfully loaded
* and is ready to be executed.
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
*/
int loader_load_program(loader_t *ldr)
{
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
if (rc != EOK)
return rc;
 
return EOK;
return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
}
 
/** Instruct loader to execute the program.
232,17 → 272,17
* After using this function, no further operations must be performed
* on the loader structure. It should be de-allocated using free().
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
*/
int loader_run(loader_t *ldr)
{
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
if (rc != EOK)
return rc;
 
ipc_hangup(ldr->phone_id);
ldr->phone_id = 0;
return EOK;
254,8 → 294,10
* After using this function, no further operations must be performed
* on the loader structure. It should be de-allocated using free().
*
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
* @param ldr Loader connection structure.
*
* @return Zero on success or negative error code.
*
*/
void loader_abort(loader_t *ldr)
{
/branches/dynload/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/dynload/uspace/lib/libc/generic/ipc.c
43,7 → 43,7
#include <libc.h>
#include <malloc.h>
#include <errno.h>
#include <libadt/list.h>
#include <adt/list.h>
#include <stdio.h>
#include <unistd.h>
#include <futex.h>
232,7 → 232,7
return;
}
 
if (callid == IPC_CALLRET_FATAL) {
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
futex_up(&ipc_futex);
/* Call asynchronous handler with error code */
if (call->callback)
241,7 → 241,7
return;
}
 
if (callid == IPC_CALLRET_TEMPORARY) {
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
futex_up(&ipc_futex);
 
call->u.msg.phoneid = phoneid;
309,7 → 309,7
callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1,
arg2, arg3, arg4);
 
if (callid == IPC_CALLRET_TEMPORARY) {
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
if (!call) {
call = ipc_prepare_async(private, callback);
if (!call)
442,7 → 442,7
call = list_get_instance(queued_calls.next, async_call_t, list);
callid = _ipc_call_async(call->u.msg.phoneid,
&call->u.msg.data);
if (callid == IPC_CALLRET_TEMPORARY) {
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
break;
}
list_remove(&call->list);
451,7 → 451,7
if (call->fid)
fibril_add_ready(call->fid);
if (callid == IPC_CALLRET_FATAL) {
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
if (call->callback)
call->callback(call->private, ENOENT, NULL);
free(call);
704,7 → 704,7
IPC_SET_ARG4(data, arg4);
IPC_SET_ARG5(data, arg5);
 
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode);
return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode);
}
 
/** Wrapper for making IPC_M_SHARE_IN calls.
/branches/dynload/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>
48,13 → 48,14
#include <futex.h>
#include <errno.h>
#include <string.h>
#include <devmap.h>
#include <ipc/vfs.h>
#include <ipc/devmap.h>
#include "../../../srv/vfs/vfs.h"
 
int vfs_phone = -1;
futex_t vfs_phone_futex = FUTEX_INITIALIZER;
static int vfs_phone = -1;
static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
static futex_t cwd_futex = FUTEX_INITIALIZER;
 
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_size = 0;
115,47 → 116,8
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,
const unsigned int flags)
{
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, flags, 0,
&answer);
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;
if (retval == EOK) {
if (handle != NULL)
*handle = (dev_handle_t) IPC_GET_ARG1(answer);
}
ipc_hangup(phone);
return retval;
}
 
int mount(const char *fs_name, const char *mp, const char *dev,
const char *opts, const unsigned int flags)
const char *opts, unsigned int flags)
{
int res;
ipcarg_t rc;
162,7 → 124,7
aid_t req;
dev_handle_t dev_handle;
res = device_get_handle(dev, &dev_handle, flags);
res = devmap_device_get_handle(dev, &dev_handle, flags);
if (res != EOK)
return res;
175,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);
236,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);
249,9 → 211,10
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
 
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
260,6 → 223,27
return _open(path, L_FILE, oflag);
}
 
int open_node(fdi_node_t *node, int oflag)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipc_call_t answer;
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;
async_wait_for(req, &rc);
async_serialize_end();
futex_up(&vfs_phone_futex);
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
int close(int fildes)
{
ipcarg_t rc;
268,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);
286,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);
313,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);
330,6 → 314,20
return -1;
}
 
int fsync(int fildes)
{
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (int) rc;
}
 
off_t lseek(int fildes, off_t offset, int whence)
{
ipcarg_t rc;
339,7 → 337,7
vfs_connect();
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
&newoffs);
 
async_serialize_end();
359,12 → 357,74
async_serialize_start();
vfs_connect();
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
async_serialize_end();
futex_up(&vfs_phone_futex);
return (int) rc;
}
 
int fstat(int fildes, struct stat *stat)
{
ipcarg_t rc;
aid_t req;
 
futex_down(&vfs_phone_futex);
async_serialize_start();
vfs_connect();
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);
 
return rc;
}
 
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();
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);
free(pa);
return rc;
}
 
DIR *opendir(const char *dirname)
{
DIR *dirp = malloc(sizeof(DIR));
412,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);
425,7 → 485,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
static int _unlink(const char *path, int lflag)
442,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);
455,7 → 515,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
int unlink(const char *path)
489,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);
558,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/dynload/uspace/lib/libc/generic/async.c
95,8 → 95,8
#include <async.h>
#include <fibril.h>
#include <stdio.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <assert.h>
#include <errno.h>
174,7 → 174,7
} connection_t;
 
/** Identifier of the incoming connection handled by the current fibril. */
static __thread connection_t *FIBRIL_connection;
static fibril_local connection_t *FIBRIL_connection;
 
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);
190,11 → 190,9
*/
static async_client_conn_t interrupt_received = default_interrupt_received;
 
 
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.
500,9 → 498,10
/* Answer all remaining messages with EHANGUP */
while (!list_empty(&FIBRIL_connection->msg_queue)) {
msg_t *msg
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link);
msg_t *msg;
msg = list_get_instance(FIBRIL_connection->msg_queue.next,
msg_t, link);
list_remove(&msg->link);
ipc_answer_0(msg->callid, EHANGUP);
free(msg);
563,7 → 562,7
}
/* Add connection to the connection hash table */
ipcarg_t key = conn->in_phone_hash;
unsigned long key = conn->in_phone_hash;
futex_down(&async_futex);
hash_table_insert(&conn_hash_table, &key, &conn->link);
588,23 → 587,28
/* Unrouted call - do some default behaviour */
if ((callid & IPC_CALLID_NOTIFICATION)) {
process_notification(callid, call);
return;
goto out;
}
switch (IPC_GET_METHOD(*call)) {
case IPC_M_CONNECT_ME:
case IPC_M_CONNECT_ME_TO:
/* Open new connection with fibril etc. */
async_new_connection(IPC_GET_ARG5(*call), callid, call,
client_connection);
return;
goto out;
}
/* Try to route the call through the connection hash table */
if (route_call(callid, call))
return;
goto out;
/* Unknown call from unknown phone - hang it up */
ipc_answer_0(callid, EHANGUP);
return;
out:
;
}
 
/** Fire all timeouts that expired. */
662,8 → 666,8
suseconds_t timeout;
if (!list_empty(&timeout_list)) {
awaiter_t *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);
680,8 → 684,8
futex_up(&async_futex);
ipc_call_t call;
ipc_callid_t callid
= ipc_wait_cycle(&call, timeout, SYNCH_FLAGS_NONE);
ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
SYNCH_FLAGS_NONE);
if (!callid) {
handle_expired_timeouts();
734,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)) {
758,13 → 762,13
*/
static void reply_received(void *arg, int retval, ipc_call_t *data)
{
futex_down(&async_futex);
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)
if ((msg->dataptr) && (data))
*msg->dataptr = *data;
write_barrier();
/branches/dynload/uspace/lib/libc/generic/task.c
31,7 → 31,7
* @{
*/
/** @file
*/
*/
 
#include <task.h>
#include <libc.h>
39,21 → 39,25
#include <errno.h>
#include <loader/loader.h>
#include <string.h>
#include <ipc/ns.h>
#include <macros.h>
#include <async.h>
 
task_id_t task_get_id(void)
{
task_id_t task_id;
 
(void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id);
 
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.
* @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)
{
65,58 → 69,102
* This is really just a convenience wrapper over the more complicated
* loader API.
*
* @param path pathname of the binary to execute
* @param argv command-line arguments
* @return ID of the newly created task or zero on error.
* @param path pathname of the binary to execute
* @param argv command-line arguments
*
* @return ID of the newly created task or zero on error.
*
*/
task_id_t task_spawn(const char *path, char *const argv[])
task_id_t task_spawn(const char *path, char *const args[])
{
loader_t *ldr;
task_id_t task_id;
int rc;
 
/* Connect to a program loader. */
ldr = loader_connect();
loader_t *ldr = loader_connect();
if (ldr == NULL)
return 0;
 
/* Get task ID. */
rc = loader_get_task_id(ldr, &task_id);
task_id_t task_id;
int rc = loader_get_task_id(ldr, &task_id);
if (rc != EOK)
goto error;
 
/* Send program pathname. */
rc = loader_set_pathname(ldr, path);
if (rc != EOK)
goto error;
 
/* Send arguments. */
rc = loader_set_args(ldr, argv);
rc = loader_set_args(ldr, args);
if (rc != EOK)
goto error;
 
/* Send default files */
fdi_node_t *files[4];
fdi_node_t stdin_node;
fdi_node_t stdout_node;
fdi_node_t stderr_node;
if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
files[0] = &stdin_node;
else
files[0] = NULL;
if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
files[1] = &stdout_node;
else
files[1] = NULL;
if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
files[2] = &stderr_node;
else
files[2] = NULL;
files[3] = NULL;
rc = loader_set_files(ldr, files);
if (rc != EOK)
goto error;
/* Load the program. */
rc = loader_load_program(ldr);
if (rc != EOK)
goto error;
 
/* Run it. */
rc = loader_run(ldr);
if (rc != EOK)
goto error;
 
/* Success */
 
free(ldr);
return task_id;
 
error:
/* Error exit */
error:
loader_abort(ldr);
free(ldr);
 
return 0;
}
 
int task_wait(task_id_t id, task_exit_t *texit, int *retval)
{
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/dynload/uspace/lib/libc/generic/fibril_sync.c
0,0 → 1,219
/*
* 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
*/
 
#include <fibril_sync.h>
#include <fibril.h>
#include <async.h>
#include <adt/list.h>
#include <futex.h>
#include <assert.h>
 
void fibril_mutex_initialize(fibril_mutex_t *fm)
{
fm->counter = 1;
list_initialize(&fm->waiters);
}
 
void fibril_mutex_lock(fibril_mutex_t *fm)
{
futex_down(&async_futex);
if (fm->counter-- <= 0) {
fibril_t *f = (fibril_t *) fibril_get_id();
list_append(&f->link, &fm->waiters);
fibril_switch(FIBRIL_TO_MANAGER);
} else {
futex_up(&async_futex);
}
}
 
bool fibril_mutex_trylock(fibril_mutex_t *fm)
{
bool locked = false;
futex_down(&async_futex);
if (fm->counter > 0) {
fm->counter--;
locked = true;
}
futex_up(&async_futex);
return locked;
}
 
static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm)
{
assert(fm->counter <= 0);
if (fm->counter++ < 0) {
link_t *tmp;
fibril_t *f;
assert(!list_empty(&fm->waiters));
tmp = fm->waiters.next;
f = list_get_instance(tmp, fibril_t, link);
list_remove(&f->link);
fibril_add_ready((fid_t) f);
}
}
 
void fibril_mutex_unlock(fibril_mutex_t *fm)
{
futex_down(&async_futex);
_fibril_mutex_unlock_unsafe(fm);
futex_up(&async_futex);
}
 
void fibril_rwlock_initialize(fibril_rwlock_t *frw)
{
frw->writers = 0;
frw->readers = 0;
list_initialize(&frw->waiters);
}
 
void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
{
futex_down(&async_futex);
if (frw->writers) {
fibril_t *f = (fibril_t *) fibril_get_id();
f->flags &= ~FIBRIL_WRITER;
list_append(&f->link, &frw->waiters);
fibril_switch(FIBRIL_TO_MANAGER);
} else {
frw->readers++;
futex_up(&async_futex);
}
}
 
void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
{
futex_down(&async_futex);
if (frw->writers || frw->readers) {
fibril_t *f = (fibril_t *) fibril_get_id();
f->flags |= FIBRIL_WRITER;
list_append(&f->link, &frw->waiters);
fibril_switch(FIBRIL_TO_MANAGER);
} else {
frw->writers++;
futex_up(&async_futex);
}
}
 
static void _fibril_rwlock_common_unlock(fibril_rwlock_t *frw)
{
futex_down(&async_futex);
assert(frw->readers || (frw->writers == 1));
if (frw->readers) {
if (--frw->readers)
goto out;
} else {
frw->writers--;
}
assert(!frw->readers && !frw->writers);
while (!list_empty(&frw->waiters)) {
link_t *tmp = frw->waiters.next;
fibril_t *f = list_get_instance(tmp, fibril_t, link);
if (f->flags & FIBRIL_WRITER) {
if (frw->readers)
break;
list_remove(&f->link);
fibril_add_ready((fid_t) f);
frw->writers++;
break;
} else {
list_remove(&f->link);
fibril_add_ready((fid_t) f);
frw->readers++;
}
}
out:
futex_up(&async_futex);
}
 
void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
{
_fibril_rwlock_common_unlock(frw);
}
 
void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
{
_fibril_rwlock_common_unlock(frw);
}
 
void fibril_condvar_initialize(fibril_condvar_t *fcv)
{
list_initialize(&fcv->waiters);
}
 
void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
{
fibril_t *f = (fibril_t *) fibril_get_id();
 
futex_down(&async_futex);
list_append(&f->link, &fcv->waiters);
_fibril_mutex_unlock_unsafe(fm);
fibril_switch(FIBRIL_TO_MANAGER);
fibril_mutex_lock(fm);
}
 
static void _fibril_condvar_wakeup_common(fibril_condvar_t *fcv, bool once)
{
link_t *tmp;
fibril_t *f;
 
futex_down(&async_futex);
while (!list_empty(&fcv->waiters)) {
tmp = fcv->waiters.next;
f = list_get_instance(tmp, fibril_t, link);
list_remove(&f->link);
fibril_add_ready((fid_t) f);
if (once)
break;
}
futex_up(&async_futex);
}
 
void fibril_condvar_signal(fibril_condvar_t *fcv)
{
_fibril_condvar_wakeup_common(fcv, true);
}
 
void fibril_condvar_broadcast(fibril_condvar_t *fcv)
{
_fibril_condvar_wakeup_common(fcv, false);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/fibril.c
33,7 → 33,7
/** @file
*/
 
#include <libadt/list.h>
#include <adt/list.h>
#include <fibril.h>
#include <thread.h>
#include <tls.h>
49,7 → 49,8
#define FIBRIL_INITIAL_STACK_PAGES_NO 1
#endif
 
/** This futex serializes access to ready_list, serialized_list and manage_list.
/**
* This futex serializes access to ready_list, serialized_list and manager_list.
*/
static atomic_t fibril_futex = FUTEX_INITIALIZER;
 
59,12 → 60,12
 
static void fibril_main(void);
 
/** Number of fibrils that are in async_serialized mode */
static int serialized_fibrils; /* Protected by async_futex */
/** Thread-local count of serialization. If >0, we must not preempt */
static __thread int serialization_count;
/** Counter for fibrils residing in async_manager */
static int fibrils_in_manager;
/** Number of threads that are executing a manager fibril. */
static int threads_in_manager;
/** Number of threads that are executing a manager fibril and are serialized. */
static int serialized_threads; /* Protected by async_futex */
/** Fibril-local count of serialization. If > 0, we must not preempt */
static fibril_local int serialization_count;
 
/** Setup fibril information into TCB structure */
fibril_t *fibril_setup(void)
143,11 → 144,11
if (list_empty(&ready_list) && list_empty(&serialized_list))
goto ret_0;
/*
* Do not preempt if there is not sufficient count of fibril
* managers.
* Do not preempt if there is not enough threads to run the
* ready fibrils which are not serialized.
*/
if (list_empty(&serialized_list) &&
fibrils_in_manager <= serialized_fibrils) {
threads_in_manager <= serialized_threads) {
goto ret_0;
}
}
194,7 → 195,7
list_append(&srcf->link, &ready_list);
else if (stype == FIBRIL_FROM_MANAGER) {
list_append(&srcf->link, &manager_list);
fibrils_in_manager--;
threads_in_manager--;
} else {
/*
* If stype == FIBRIL_TO_MANAGER, don't put ourselves to
208,10 → 209,10
if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
dstf = list_get_instance(manager_list.next, fibril_t, link);
if (serialization_count && stype == FIBRIL_TO_MANAGER) {
serialized_fibrils++;
serialized_threads++;
srcf->flags |= FIBRIL_SERIALIZED;
}
fibrils_in_manager++;
threads_in_manager++;
 
if (stype == FIBRIL_FROM_DEAD)
dstf->clean_after_me = srcf;
219,7 → 220,7
if (!list_empty(&serialized_list)) {
dstf = list_get_instance(serialized_list.next, fibril_t,
link);
serialized_fibrils--;
serialized_threads--;
} else {
dstf = list_get_instance(ready_list.next, fibril_t,
link);
269,7 → 270,7
 
/** Add a fibril to the ready list.
*
* @param fid Pinter to the fibril structure of the fibril to be
* @param fid Pointer to the fibril structure of the fibril to be
* added.
*/
void fibril_add_ready(fid_t fid)
287,7 → 288,8
 
/** Add a fibril to the manager list.
*
* @param fid Pinter to the fibril structure of the fibril to be added.
* @param fid Pointer to the fibril structure of the fibril to be
* added.
*/
void fibril_add_manager(fid_t fid)
{
314,7 → 316,8
 
/** Return fibril id of the currently running fibril.
*
* @return Fibril ID of the currently running pseudo thread.
* @return fibril ID of the currently running fibril.
*
*/
fid_t fibril_get_id(void)
{
321,13 → 324,14
return (fid_t) __tcb_get()->fibril_data;
}
 
/** Disable preemption
/** Disable preemption
*
* If the fibril wants to send several message in a row and does not want to be
* preempted, it should start async_serialize_start() in the beginning of
* communication and async_serialize_end() in the end. If it is a true
* multithreaded application, it should protect the communication channel by a
* futex as well. Interrupt messages can still be preempted.
* futex as well.
*
*/
void fibril_inc_sercount(void)
{
/branches/dynload/uspace/lib/libc/generic/libc.c
27,28 → 27,29
*/
 
/** @addtogroup lc Libc
* @brief HelenOS C library
* @brief HelenOS C library
* @{
* @}
*/
 
/** @addtogroup libc generic
* @ingroup lc
* @{
*/
 
/** @file
*/
*/
 
#include <libc.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <tls.h>
#include <thread.h>
#include <fibril.h>
#include <io/stream.h>
#include <ipc/ipc.h>
#include <async.h>
#include <as.h>
#include <console.h>
#include <loader/pcb.h>
 
/* From librtld. */
55,11 → 56,8
#include <rtld.h>
#include <string.h>
 
extern char _heap;
extern int main(int argc, char *argv[]);
 
int _errno;
 
void _exit(int status)
{
thread_exit(status);
67,18 → 65,19
 
void __main(void *pcb_ptr)
{
fibril_t *f;
int retval;
 
__heap_init();
__async_init();
fibril_t *fibril = fibril_setup();
__tcb_set(fibril->tcb);
/* Save the PCB pointer */
__pcb = (pcb_t *) pcb_ptr;
int argc;
char **argv;
 
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ);
_async_init();
f = fibril_setup();
__tcb_set(f->tcb);
/* Save the PCB pointer */
__pcb = (pcb_t *)pcb_ptr;
 
#ifdef __IN_SHARED_LIBC__
if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
runtime_env = (runtime_env_t *) __pcb->rtld_runtime;
88,13 → 87,17
if (__pcb == NULL) {
argc = 0;
argv = NULL;
__stdio_init(0, NULL);
} else {
argc = __pcb->argc;
argv = __pcb->argv;
__stdio_init(__pcb->filc, __pcb->filv);
}
retval = main(argc, argv);
 
main(argc, argv);
console_flush();
__stdio_done();
(void) task_retval(retval);
}
 
void __exit(void)
/branches/dynload/uspace/lib/libc/generic/devmap.c
0,0 → 1,289
/*
* Copyright (c) 2007 Josef Cejka
* 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.
*/
 
#include <string.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/devmap.h>
#include <devmap.h>
#include <async.h>
#include <errno.h>
 
static int devmap_phone_driver = -1;
static int devmap_phone_client = -1;
 
/** Get phone to device mapper task. */
int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
{
switch (iface) {
case DEVMAP_DRIVER:
if (devmap_phone_driver >= 0)
return devmap_phone_driver;
if (flags & IPC_FLAG_BLOCKING)
devmap_phone_driver = ipc_connect_me_to_blocking(PHONE_NS,
SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
else
devmap_phone_driver = ipc_connect_me_to(PHONE_NS,
SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
return devmap_phone_driver;
case DEVMAP_CLIENT:
if (devmap_phone_client >= 0)
return devmap_phone_client;
if (flags & IPC_FLAG_BLOCKING)
devmap_phone_client = ipc_connect_me_to_blocking(PHONE_NS,
SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
else
devmap_phone_client = ipc_connect_me_to(PHONE_NS,
SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
return devmap_phone_client;
default:
return -1;
}
}
 
void devmap_hangup_phone(devmap_interface_t iface)
{
switch (iface) {
case DEVMAP_DRIVER:
if (devmap_phone_driver >= 0) {
ipc_hangup(devmap_phone_driver);
devmap_phone_driver = -1;
}
break;
case DEVMAP_CLIENT:
if (devmap_phone_client >= 0) {
ipc_hangup(devmap_phone_client);
devmap_phone_client = -1;
}
break;
default:
break;
}
}
 
/** Register new driver with devmap. */
int devmap_driver_register(const char *name, async_client_conn_t conn)
{
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
if (phone < 0)
return phone;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return -1;
}
async_set_client_connection(conn);
ipcarg_t callback_phonehash;
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
async_wait_for(req, &retval);
async_serialize_end();
return retval;
}
 
/** Register new device.
*
* @param name Device name.
* @param handle Output: Handle to the created instance of device.
*
*/
int devmap_device_register(const char *name, dev_handle_t *handle)
{
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
if (phone < 0)
return phone;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0,
&answer);
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return retval;
}
async_wait_for(req, &retval);
async_serialize_end();
if (retval != EOK) {
if (handle != NULL)
*handle = -1;
return retval;
}
if (handle != NULL)
*handle = (dev_handle_t) IPC_GET_ARG1(answer);
return retval;
}
 
int devmap_device_get_handle(const char *name, dev_handle_t *handle, unsigned int flags)
{
int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
if (phone < 0)
return phone;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
&answer);
ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return retval;
}
async_wait_for(req, &retval);
async_serialize_end();
if (retval != EOK) {
if (handle != NULL)
*handle = (dev_handle_t) -1;
return retval;
}
if (handle != NULL)
*handle = (dev_handle_t) IPC_GET_ARG1(answer);
return retval;
}
 
int devmap_device_connect(dev_handle_t handle, unsigned int flags)
{
int phone;
if (flags & IPC_FLAG_BLOCKING) {
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, handle);
} else {
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, handle);
}
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);
if (phone < 0)
return 0;
ipcarg_t count;
int retval = async_req_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count);
if (retval != EOK)
return 0;
return count;
}
 
ipcarg_t devmap_device_get_devices(ipcarg_t count, dev_desc_t *data)
{
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
if (phone < 0)
return 0;
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer);
ipcarg_t retval = ipc_data_read_start(phone, data, count * sizeof(dev_desc_t));
if (retval != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return 0;
}
async_wait_for(req, &retval);
async_serialize_end();
if (retval != EOK)
return 0;
return IPC_GET_ARG1(answer);
}
/branches/dynload/uspace/lib/libc/generic/mem.c
95,7 → 95,7
 
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
{
int i, j;
size_t i, j;
struct along *adst = dst;
const struct along *asrc = src;
 
/branches/dynload/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/dynload/uspace/lib/libc/generic/io/sprintf.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/vsprintf.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/fprintf.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/stream.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/stdio.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/printf.c
34,23 → 34,43
 
#include <io/printf_core.h>
#include <stdio.h>
#include <stdio.h>
 
/** Print formatted text.
* @param fmt format string
*
* @param stream Output stream
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int fprintf(FILE *stream, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vfprintf(stream, fmt, args);
va_end(args);
return ret;
}
 
/** Print formatted text to stdout.
*
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int printf(const char *fmt, ...)
{
int ret;
va_list args;
 
va_start(args, fmt);
 
ret = vprintf(fmt, args);
int ret = vprintf(fmt, args);
va_end(args);
 
return ret;
}
 
/branches/dynload/uspace/lib/libc/generic/io/console.c
0,0 → 1,113
/*
* 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/console.h>
#include <ipc/console.h>
 
void console_clear(int phone)
{
async_msg_0(phone, CONSOLE_CLEAR);
}
 
int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols)
{
return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols);
}
 
void console_set_style(int phone, int style)
{
async_msg_1(phone, CONSOLE_SET_STYLE, style);
}
 
void console_set_color(int phone, int fg_color, int bg_color, int flags)
{
async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
}
 
void console_set_rgb_color(int phone, int fg_color, int bg_color)
{
async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
}
 
void console_cursor_visibility(int phone, bool show)
{
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);
}
 
void console_goto(int phone, ipcarg_t row, ipcarg_t col)
{
async_msg_2(phone, CONSOLE_GOTO, row, col);
}
 
bool console_get_event(int phone, console_event_t *event)
{
ipcarg_t type;
ipcarg_t key;
ipcarg_t mods;
ipcarg_t c;
int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
if (rc < 0)
return false;
event->type = type;
event->key = key;
event->mods = mods;
event->c = c;
return true;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/snprintf.c
37,21 → 37,23
#include <io/printf_core.h>
 
/** Print formatted to the given buffer with limited size.
* @param str buffer
* @param size buffer size
* @param fmt format string
*
* @param str Buffer
* @param size Buffer size
* @param fmt Format string
*
* \see For more details about format string see printf_core.
*
*/
int snprintf(char *str, size_t size, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
va_start(args, fmt);
ret = vsnprintf(str, size, fmt, args);
 
int ret = vsnprintf(str, size, fmt, args);
va_end(args);
 
return ret;
}
 
/branches/dynload/uspace/lib/libc/generic/io/asprintf.c
36,42 → 36,52
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/printf_core.h>
 
static int asprintf_prewrite(const char *str, size_t count, void *unused)
static int asprintf_str_write(const char *str, size_t count, void *unused)
{
return count;
return str_nlength(str, count);
}
 
static int asprintf_wstr_write(const wchar_t *str, size_t count, void *unused)
{
return wstr_nlength(str, count);
}
 
/** Allocate and print to string.
*
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format strin.
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format string.
*
* @return Number of characters printed or a negative error code.
* @return Number of characters printed or a negative error code.
*
*/
int asprintf(char **strp, const char *fmt, ...)
{
struct printf_spec ps = {
asprintf_prewrite,
NULL
asprintf_str_write,
asprintf_wstr_write,
NULL
};
int ret;
va_list args;
 
va_start(args, fmt);
ret = printf_core(fmt, &ps, args);
int ret = printf_core(fmt, &ps, args);
va_end(args);
if (ret > 0) {
*strp = malloc(ret + 20);
if (!*strp)
*strp = malloc(STR_BOUNDS(ret) + 1);
if (*strp == NULL)
return -1;
va_start(args, fmt);
vsprintf(*strp, fmt, args);
va_end(args);
vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args);
va_end(args);
}
 
return ret;
}
 
/branches/dynload/uspace/lib/libc/generic/io/io.c
30,98 → 30,564
* @{
*/
/** @file
*/
*/
 
#include <libc.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <io/io.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <console.h>
#include <bool.h>
#include <malloc.h>
#include <io/klog.h>
#include <vfs/vfs.h>
#include <ipc/devmap.h>
#include <adt/list.h>
 
const static char nl = '\n';
static void _fflushbuf(FILE *stream);
 
int puts(const char *str)
static FILE stdin_null = {
.fd = -1,
.error = true,
.eof = true,
.klog = false,
.phone = -1,
.btype = _IONBF,
.buf = NULL,
.buf_size = 0,
.buf_head = NULL
};
 
static FILE stdout_klog = {
.fd = -1,
.error = false,
.eof = false,
.klog = true,
.phone = -1,
.btype = _IOLBF,
.buf = NULL,
.buf_size = BUFSIZ,
.buf_head = NULL
};
 
static FILE stderr_klog = {
.fd = -1,
.error = false,
.eof = false,
.klog = true,
.phone = -1,
.btype = _IONBF,
.buf = NULL,
.buf_size = 0,
.buf_head = NULL
};
 
FILE *stdin = NULL;
FILE *stdout = NULL;
FILE *stderr = NULL;
 
static LIST_INITIALIZE(files);
 
void __stdio_init(int filc, fdi_node_t *filv[])
{
size_t count;
if (filc > 0) {
stdin = fopen_node(filv[0], "r");
} else {
stdin = &stdin_null;
list_append(&stdin->link, &files);
}
if (str == NULL)
return putnchars("(NULL)", 6);
if (filc > 1) {
stdout = fopen_node(filv[1], "w");
} else {
stdout = &stdout_klog;
list_append(&stdout->link, &files);
}
for (count = 0; str[count] != 0; count++);
if (filc > 2) {
stderr = fopen_node(filv[2], "w");
} else {
stderr = &stderr_klog;
list_append(&stderr->link, &files);
}
}
 
void __stdio_done(void)
{
link_t *link = files.next;
if (console_write((void *) str, count) == count) {
if (console_write(&nl, 1) == 1)
return 0;
while (link != &files) {
FILE *file = list_get_instance(link, FILE, link);
fclose(file);
link = files.next;
}
}
 
static bool parse_mode(const char *mode, int *flags)
{
/* Parse mode except first character. */
const char *mp = mode;
if (*mp++ == 0) {
errno = EINVAL;
return false;
}
return EOF;
if ((*mp == 'b') || (*mp == 't'))
mp++;
bool plus;
if (*mp == '+') {
mp++;
plus = true;
} else
plus = false;
if (*mp != 0) {
errno = EINVAL;
return false;
}
/* 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 false;
}
*flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
default:
errno = EINVAL;
return false;
}
return true;
}
 
/** Put count chars from buffer to stdout without adding newline
* @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
* @param count
* @return 0 on succes, EOF on fail
*/
int putnchars(const char *buf, size_t count)
/** Set stream buffer. */
void setvbuf(FILE *stream, void *buf, int mode, size_t size)
{
if (console_write((void *) buf, count) == count)
return 0;
stream->btype = mode;
stream->buf = buf;
stream->buf_size = size;
stream->buf_head = stream->buf;
}
 
static void _setvbuf(FILE *stream)
{
/* FIXME: Use more complex rules for setting buffering options. */
return EOF;
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);
}
}
 
/** Same as puts, but does not print newline at end
/** 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;
}
 
/** Open a stream.
*
* @param path Path of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*
*/
int putstr(const char *str)
FILE *fopen(const char *path, const char *mode)
{
size_t count;
int flags;
if (!parse_mode(mode, &flags))
return NULL;
if (str == NULL)
return putnchars("(NULL)", 6);
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = open(path, flags, 0666);
if (stream->fd < 0) {
/* errno was set by open() */
free(stream);
return NULL;
}
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
_setvbuf(stream);
list_append(&stream->link, &files);
return stream;
}
 
for (count = 0; str[count] != 0; count++);
if (console_write((void *) str, count) == count)
return 0;
FILE *fdopen(int fd, const char *mode)
{
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
return EOF;
stream->fd = fd;
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
_setvbuf(stream);
list_append(&stream->link, &files);
return stream;
}
 
int putchar(int c)
FILE *fopen_node(fdi_node_t *node, const char *mode)
{
char buf[STR_BOUNDS(1)];
size_t offs;
int flags;
if (!parse_mode(mode, &flags))
return NULL;
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
stream->fd = open_node(node, flags);
if (stream->fd < 0) {
/* errno was set by open_node() */
free(stream);
return NULL;
}
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
_setvbuf(stream);
list_append(&stream->link, &files);
return stream;
}
 
offs = 0;
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK)
int fclose(FILE *stream)
{
int rc = 0;
fflush(stream);
if (stream->phone >= 0)
ipc_hangup(stream->phone);
if (stream->fd >= 0)
rc = close(stream->fd);
list_remove(&stream->link);
if ((stream != &stdin_null)
&& (stream != &stdout_klog)
&& (stream != &stderr_klog))
free(stream);
stream = NULL;
if (rc != 0) {
/* errno was set by close() */
return EOF;
}
return 0;
}
 
if (console_write((void *) buf, offs) == offs)
return c;
/** Read from a stream.
*
* @param buf Destination buffer.
* @param size Size of each record.
* @param nmemb Number of records to read.
* @param stream Pointer to the stream.
*
*/
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
{
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);
if (rd < 0)
stream->error = true;
else if (rd == 0)
stream->eof = true;
else {
left -= rd;
done += rd;
}
}
return (done / size);
}
 
return EOF;
static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
{
size_t left = size * nmemb;
size_t done = 0;
while ((left > 0) && (!stream->error)) {
ssize_t wr;
if (stream->klog)
wr = klog_write(buf + done, left);
else
wr = write(stream->fd, buf + done, left);
if (wr <= 0)
stream->error = true;
else {
left -= wr;
done += wr;
}
}
return (done / size);
}
 
int getchar(void)
/** Drain stream buffer, do not sync stream. */
static void _fflushbuf(FILE *stream)
{
unsigned char c;
size_t bytes_used;
console_flush();
if (read_stdin((void *) &c, 1) == 1)
return c;
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;
}
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param stream Pointer to the stream.
*
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
{
uint8_t *data;
size_t bytes_left;
size_t now;
size_t buf_free;
size_t total_written;
size_t i;
uint8_t b;
bool need_flush;
/* If not buffered stream, write out directly. */
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)) {
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))
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);
need_flush = false;
}
}
if (need_flush)
fflush(stream);
return (total_written / size);
}
 
int fputc(wchar_t c, FILE *stream)
{
char buf[STR_BOUNDS(1)];
size_t sz = 0;
if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) {
size_t wr = fwrite(buf, sz, 1, stream);
if (wr < sz)
return EOF;
return (int) c;
}
return EOF;
}
 
int fflush(FILE *f)
int putchar(wchar_t c)
{
/* Dummy implementation */
(void) f;
console_flush();
return fputc(c, stdout);
}
 
int fputs(const char *str, FILE *stream)
{
return fwrite(str, str_size(str), 1, stream);
}
 
int puts(const char *str)
{
return fputs(str, stdout);
}
 
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;
return (int) c;
}
 
int getchar(void)
{
return fgetc(stdin);
}
 
int fseek(FILE *stream, long offset, int origin)
{
off_t rc = lseek(stream->fd, offset, origin);
if (rc == (off_t) (-1)) {
/* errno has been set by lseek. */
return -1;
}
stream->eof = false;
return 0;
}
 
void rewind(FILE *stream)
{
(void) fseek(stream, 0, SEEK_SET);
}
 
int fflush(FILE *stream)
{
_fflushbuf(stream);
if (stream->klog) {
klog_update();
return EOK;
}
if (stream->fd >= 0)
return fsync(stream->fd);
return ENOENT;
}
 
int feof(FILE *stream)
{
return stream->eof;
}
 
int ferror(FILE *stream)
{
return stream->error;
}
 
int fphone(FILE *stream)
{
if (stream->fd >= 0) {
if (stream->phone < 0)
stream->phone = fd_phone(stream->fd);
return stream->phone;
}
return -1;
}
 
int fnode(FILE *stream, fdi_node_t *node)
{
if (stream->fd >= 0)
return fd_node(stream->fd, node);
return ENOENT;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/vprintf.c
38,37 → 38,25
#include <io/printf_core.h>
#include <futex.h>
#include <async.h>
#include <console.h>
#include <string.h>
 
static atomic_t printf_futex = FUTEX_INITIALIZER;
 
static int vprintf_str_write(const char *str, size_t size, void *data)
static int vprintf_str_write(const char *str, size_t size, void *stream)
{
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;
size_t wr = fwrite(str, 1, size, (FILE *) stream);
return str_nlength(str, wr);
}
 
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *stream)
{
size_t offset = 0;
size_t boff;
count_t chars = 0;
char buf[4];
size_t chars = 0;
while (offset < size) {
boff = 0;
chr_encode(str[chars], buf, &boff, 4);
console_write(buf, boff);
if (fputc(str[chars], (FILE *) stream) <= 0)
break;
chars++;
offset += sizeof(wchar_t);
}
76,33 → 64,55
return chars;
}
 
 
/** Print formatted text.
* @param fmt format string
* @param ap format parameters
*
* @param stream Output stream
* @param fmt Format string
* @param ap Format parameters
*
* \see For more details about format string see printf_core.
*
*/
int vprintf(const char *fmt, va_list ap)
int vfprintf(FILE *stream, const char *fmt, va_list ap)
{
struct printf_spec ps = {
vprintf_str_write,
vprintf_wstr_write,
NULL
stream
};
/*
* Prevent other threads to execute printf_core()
*/
futex_down(&printf_futex);
/*
* Prevent other pseudo threads of the same thread
* Prevent other fibrils of the same thread
* to execute printf_core()
*/
async_serialize_start();
int ret = printf_core(fmt, &ps, ap);
async_serialize_end();
futex_up(&printf_futex);
return ret;
}
 
/** Print formatted text to stdout.
*
* @param file Output stream
* @param fmt Format string
* @param ap Format parameters
*
* \see For more details about format string see printf_core.
*
*/
int vprintf(const char *fmt, va_list ap)
{
return vfprintf(stdout, fmt, ap);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/vsnprintf.c
82,7 → 82,7
* with the trailing zero => print only a part
* of string
*/
index_t index = 0;
size_t index = 0;
while (index < size) {
wchar_t uc = str_decode(str, &index, size);
130,7 → 130,7
*/
static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
{
index_t index = 0;
size_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
/branches/dynload/uspace/lib/libc/generic/io/printf_core.c
173,7 → 173,7
*/
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
211,7 → 211,7
*/
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
254,12 → 254,12
return printf_putstr(nullstr, ps);
 
/* Print leading spaces. */
count_t strw = str_length(str);
size_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
count_t counter = 0;
size_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
301,9 → 301,6
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)
310,7 → 307,7
precision = strw;
/* Left padding */
count_t counter = 0;
size_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
432,7 → 429,7
}
width -= precision + size - number_size;
count_t counter = 0;
size_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
595,7 → 592,7
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
count_t counter = 0; /* Number of characters printed */
size_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
/branches/dynload/uspace/lib/libc/generic/io/klog.c
0,0 → 1,53
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* 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 <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <io/klog.h>
 
size_t klog_write(const void *buf, size_t size)
{
return (size_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
}
 
void klog_update(void)
{
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/adt/hash_table.c
0,0 → 1,196
/*
* Copyright (c) 2008 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
*/
 
/*
* This is an implementation of generic chained hash table.
*/
 
#include <adt/hash_table.h>
#include <adt/list.h>
#include <unistd.h>
#include <malloc.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
 
/** Create chained hash table.
*
* @param h Hash table structure. Will be initialized by this call.
* @param m Number of hash table buckets.
* @param max_keys Maximal number of keys needed to identify an item.
* @param op Hash table operations structure.
* @return True on success
*/
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
hash_table_operations_t *op)
{
hash_count_t i;
 
assert(h);
assert(op && op->hash && op->compare);
assert(max_keys > 0);
h->entry = malloc(m * sizeof(link_t));
if (!h->entry) {
printf("cannot allocate memory for hash table\n");
return false;
}
memset((void *) h->entry, 0, m * sizeof(link_t));
for (i = 0; i < m; i++)
list_initialize(&h->entry[i]);
h->entries = m;
h->max_keys = max_keys;
h->op = op;
return true;
}
 
/** Destroy a hash table instance.
*
* @param h Hash table to be destroyed.
*/
void hash_table_destroy(hash_table_t *h)
{
assert(h);
assert(h->entry);
free(h->entry);
}
 
/** Insert item into a hash table.
*
* @param h Hash table.
* @param key Array of all keys necessary to compute hash index.
* @param item Item to be inserted into the hash table.
*/
void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
{
hash_index_t chain;
 
assert(item);
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
list_append(item, &h->entry[chain]);
}
 
/** Search hash table for an item matching keys.
*
* @param h Hash table.
* @param key Array of all keys needed to compute hash index.
*
* @return Matching item on success, NULL if there is no such item.
*/
link_t *hash_table_find(hash_table_t *h, unsigned long key[])
{
link_t *cur;
hash_index_t chain;
 
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
for (cur = h->entry[chain].next; cur != &h->entry[chain];
cur = cur->next) {
if (h->op->compare(key, h->max_keys, cur)) {
/*
* The entry is there.
*/
return cur;
}
}
return NULL;
}
 
/** Remove all matching items from hash table.
*
* For each removed item, h->remove_callback() is called.
*
* @param h Hash table.
* @param key Array of keys that will be compared against items of
* the hash table.
* @param keys Number of keys in the 'key' array.
*/
void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
{
hash_index_t chain;
link_t *cur;
 
assert(h && h->op && h->op->hash && h->op->compare &&
h->op->remove_callback);
assert(keys <= h->max_keys);
if (keys == h->max_keys) {
 
/*
* All keys are known, hash_table_find() can be used to find the
* entry.
*/
cur = hash_table_find(h, key);
if (cur) {
list_remove(cur);
h->op->remove_callback(cur);
}
return;
}
/*
* Fewer keys were passed.
* Any partially matching entries are to be removed.
*/
for (chain = 0; chain < h->entries; chain++) {
for (cur = h->entry[chain].next; cur != &h->entry[chain];
cur = cur->next) {
if (h->op->compare(key, keys, cur)) {
link_t *hlp;
hlp = cur;
cur = cur->prev;
list_remove(hlp);
h->op->remove_callback(hlp);
continue;
}
}
}
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/adt/list.c
0,0 → 1,112
/*
* Copyright (c) 2004 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
*/
 
#include <adt/list.h>
 
 
/** Check for membership
*
* Check whether link is contained in the list head.
* The membership is defined as pointer equivalence.
*
* @param link Item to look for.
* @param head List to look in.
*
* @return true if link is contained in head, false otherwise.
*
*/
int list_member(const link_t *link, const link_t *head)
{
int found = 0;
link_t *hlp = head->next;
while (hlp != head) {
if (hlp == link) {
found = 1;
break;
}
hlp = hlp->next;
}
return found;
}
 
 
/** Concatenate two lists
*
* Concatenate lists head1 and head2, producing a single
* list head1 containing items from both (in head1, head2
* order) and empty list head2.
*
* @param head1 First list and concatenated output
* @param head2 Second list and empty output.
*
*/
void list_concat(link_t *head1, link_t *head2)
{
if (list_empty(head2))
return;
head2->next->prev = head1->prev;
head2->prev->next = head1;
head1->prev->next = head2->next;
head1->prev = head2->prev;
list_initialize(head2);
}
 
 
/** Count list items
*
* Return the number of items in the list.
*
* @param link List to count.
*
* @return Number of items in the list.
*
*/
unsigned int list_count(const link_t *link)
{
unsigned int count = 0;
link_t *hlp = link->next;
while (hlp != link) {
count++;
hlp = hlp->next;
}
return count;
}
 
/** @}
*/
/branches/dynload/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);
}
 
/branches/dynload/uspace/lib/libc/Makefile
33,6 → 33,7
LIBC_PREFIX = $(shell pwd)
SOFTINT_PREFIX = ../softint
 
 
## Setup toolchain
#
 
50,11 → 51,13
generic/ddi.c \
generic/as.c \
generic/cap.c \
generic/console.c \
generic/devmap.c \
generic/event.c \
generic/errno.c \
generic/mem.c \
generic/string.c \
generic/fibril.c \
generic/fibril_sync.c \
generic/pcb.c \
generic/smc.c \
generic/thread.c \
64,16 → 67,13
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/klog.c \
generic/io/snprintf.c \
generic/io/vprintf.c \
generic/io/vsprintf.c \
generic/io/vsnprintf.c \
generic/io/printf_core.c \
malloc/malloc.c \
generic/io/console.c \
generic/malloc.c \
generic/sysinfo.c \
generic/ipc.c \
generic/async.c \
80,12 → 80,11
generic/dlfcn.c \
generic/loader.c \
generic/getopt.c \
generic/libadt/list.o \
generic/libadt/hash_table.o \
generic/adt/list.o \
generic/adt/hash_table.o \
generic/time.c \
generic/err.c \
generic/stdlib.c \
generic/kbd.c \
generic/mman.c \
generic/udebug.c \
generic/vfs/vfs.c \
/branches/dynload/uspace/lib/libc/arch/sparc64/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/sparc64/include/types.h
49,8 → 49,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/sparc64/include/stack.h
45,6 → 45,11
*/
#define STACK_WINDOW_SAVE_AREA_SIZE (16 * STACK_ITEM_SIZE)
 
/*
* Six extended words for first six arguments.
*/
#define STACK_ARG_SAVE_AREA_SIZE (6 * STACK_ITEM_SIZE)
 
/**
* By convention, the actual top of the stack is %sp + STACK_BIAS.
*/
/branches/dynload/uspace/lib/libc/arch/sparc64/include/fibril.h
39,7 → 39,7
#include <sys/types.h>
#include <align.h>
 
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE)
 
#ifdef context_set
#undef context_set
/branches/dynload/uspace/lib/libc/arch/sparc64/Makefile.inc
38,5 → 38,7
CFLAGS += -mcpu=ultrasparc -m64
LFLAGS += -no-check-sections -N
 
ENDIANESS = BE
 
BFD_NAME = elf64-sparc
BFD_ARCH = sparc
/branches/dynload/uspace/lib/libc/arch/ia64/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/ia64/include/types.h
49,8 → 49,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/ia64/Makefile.inc
31,9 → 31,6
 
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \
arch/$(UARCH)/src/fibril.S \
40,5 → 37,10
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/ddi.c
 
CFLAGS += -fno-unwind-tables
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
 
ENDIANESS = LE
 
BFD_NAME = elf64-ia64-little
BFD_ARCH = ia64-elf64
/branches/dynload/uspace/lib/libc/arch/arm32/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/arm32/include/tls.h
40,7 → 40,7
 
#define CONFIG_TLS_VARIANT_1
 
/** Offsets for accessing __thread variables are shifted 8 bytes higher. */
/** Offsets for accessing thread-local variables are shifted 8 bytes higher. */
#define ARM_TP_OFFSET (-8)
 
/** TCB (Thread Control Block) struct.
/branches/dynload/uspace/lib/libc/arch/arm32/include/types.h
50,8 → 50,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/arm32/include/fibril.h
38,7 → 38,7
 
#include <sys/types.h>
#include <align.h>
#include "thread.h"
#include <thread.h>
 
/** Size of a stack item */
#define STACK_ITEM_SIZE 4
/branches/dynload/uspace/lib/libc/arch/arm32/Makefile.inc
32,9 → 32,6
 
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
41,5 → 38,10
arch/$(UARCH)/src/tls.c \
arch/$(UARCH)/src/eabi.S
 
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
 
ENDIANESS = LE
 
BFD_NAME = elf32-littlearm
BFD_ARCH = arm
/branches/dynload/uspace/lib/libc/arch/mips32eb/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/mips32eb/Makefile.inc
31,13 → 31,15
 
TARGET = mips-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
CFLAGS += -mips3
LFLAGS += -N
 
ENDIANESS = BE
 
BFD_ARCH = mips
BFD_NAME = elf32-tradbigmips
/branches/dynload/uspace/lib/libc/arch/ppc32/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/ppc32/include/types.h
49,8 → 49,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/ppc32/Makefile.inc
40,5 → 40,7
AFLAGS += -a32
LFLAGS += -N
 
ENDIANESS = BE
 
BFD_NAME = elf32-powerpc
BFD_ARCH = powerpc:common
/branches/dynload/uspace/lib/libc/arch/amd64/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/amd64/include/types.h
49,8 → 49,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/amd64/Makefile.inc
38,5 → 38,7
 
LFLAGS += -N
 
ENDIANESS = LE
 
BFD_NAME = elf64-x86-64
BFD_ARCH = i386:x86-64
/branches/dynload/uspace/lib/libc/arch/mips32/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/mips32/include/types.h
50,8 → 50,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/mips32/Makefile.inc
31,11 → 31,14
 
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
arch/$(UARCH)/src/fibril.S \
arch/$(UARCH)/src/tls.c
 
CFLAGS += -mips3
 
ENDIANESS = LE
 
BFD_ARCH = mips
BFD_NAME = elf32-tradlittlemips
/branches/dynload/uspace/lib/libc/arch/ia32/include/byteorder.h
File deleted
/branches/dynload/uspace/lib/libc/arch/ia32/include/types.h
49,8 → 49,6
 
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;
 
/branches/dynload/uspace/lib/libc/arch/ia32/Makefile.inc
39,5 → 39,7
 
LFLAGS += -N
 
ENDIANESS = LE
 
BFD_NAME = elf32-i386
BFD_ARCH = i386