Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 4691 → Rev 4690

/branches/dynload/kernel/generic/src/main/main.c
153,7 → 153,7
config.stack_base = config.base + config.kernel_size;
/* Avoid placing stack on top of init */
size_t i;
count_t i;
for (i = 0; i < init.cnt; i++) {
if (PA_overlaps(config.stack_base, config.stack_size,
init.tasks[i].addr, init.tasks[i].size))
233,7 → 233,7
/* Slab must be initialized after we know the number of processors. */
LOG_EXEC(slab_enable_cpucache());
printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n",
printf("Detected %" PRIc " CPU(s), %" PRIu64" MiB free memory\n",
config.cpu_count, SIZE2MB(zone_total_size()));
LOG_EXEC(cpu_init());
247,9 → 247,9
LOG_EXEC(futex_init());
if (init.cnt > 0) {
size_t i;
count_t i;
for (i = 0; i < init.cnt; i++)
LOG("init[%" PRIs "].addr=%#" PRIp ", init[%" PRIs
LOG("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
"].size=%#" PRIs, i, init.tasks[i].addr, i,
init.tasks[i].size);
} else
/branches/dynload/kernel/generic/src/main/kinit.c
127,7 → 127,7
}
if (config.cpu_count > 1) {
size_t i;
count_t i;
/*
* For each CPU, create its load balancing thread.
140,7 → 140,7
spinlock_unlock(&thread->lock);
thread_ready(thread);
} else
printf("Unable to create kcpulb thread for cpu" PRIs "\n", i);
printf("Unable to create kcpulb thread for cpu" PRIc "\n", i);
}
}
#endif /* CONFIG_SMP */
168,12 → 168,12
/*
* Create user tasks, load RAM disk images.
*/
size_t i;
count_t i;
program_t programs[CONFIG_INIT_TASKS];
for (i = 0; i < init.cnt; i++) {
if (init.tasks[i].addr % FRAME_SIZE) {
printf("init[%" PRIs "].addr is not frame aligned\n", i);
printf("init[%" PRIc "].addr is not frame aligned\n", i);
continue;
}
213,7 → 213,7
int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size);
if (rd != RE_OK)
printf("Init binary %" PRIs " not used (error %d)\n", i, rd);
printf("Init binary %" PRIc " not used (error %d)\n", i, rd);
}
}
/branches/dynload/kernel/generic/src/main/uinit.c
79,14 → 79,6
uarg.uspace_thread_arg = NULL;
 
free((uspace_arg_t *) arg);
/*
* Disable interrupts so that the execution of userspace() is not
* disturbed by any interrupts as some of the userspace()
* implementations will switch to the userspace stack before switching
* the mode.
*/
(void) interrupts_disable();
userspace(&uarg);
}
 
/branches/dynload/kernel/generic/src/ipc/kbox.c
248,7 → 248,7
return EINVAL;
}
 
newphid = phone_alloc(TASK);
newphid = phone_alloc();
if (newphid < 0) {
mutex_unlock(&ta->kb.cleanup_lock);
return ELIMIT;
/branches/dynload/kernel/generic/src/ipc/event.c
64,8 → 64,8
}
}
 
static int event_subscribe(event_type_t evno, unative_t method,
answerbox_t *answerbox)
static int
event_subscribe(event_type_t evno, unative_t method, answerbox_t *answerbox)
{
if (evno >= EVENT_END)
return ELIMIT;
122,7 → 122,8
}
}
 
void event_notify(event_type_t evno, unative_t a1, unative_t a2, unative_t a3,
void
event_notify(event_type_t evno, unative_t a1, unative_t a2, unative_t a3,
unative_t a4, unative_t a5)
{
ASSERT(evno < EVENT_END);
140,11 → 141,9
IPC_SET_ARG4(call->data, a4);
IPC_SET_ARG5(call->data, a5);
ipl_t ipl = interrupts_disable();
spinlock_lock(&events[evno].answerbox->irq_lock);
list_append(&call->link, &events[evno].answerbox->irq_notifs);
spinlock_unlock(&events[evno].answerbox->irq_lock);
interrupts_restore(ipl);
waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
}
/branches/dynload/kernel/generic/src/ipc/sysipc.c
93,8 → 93,6
static inline int method_is_forwardable(unative_t method)
{
switch (method) {
case IPC_M_CONNECTION_CLONE:
case IPC_M_CONNECT_ME:
case IPC_M_PHONE_HUNGUP:
/* This message is meant only for the original recipient. */
return 0;
142,8 → 140,6
static inline int answer_need_old(call_t *call)
{
switch (IPC_GET_METHOD(call->data)) {
case IPC_M_CONNECTION_CLONE:
case IPC_M_CONNECT_ME:
case IPC_M_CONNECT_TO_ME:
case IPC_M_CONNECT_ME_TO:
case IPC_M_SHARE_OUT:
186,48 → 182,9
if (!olddata)
return 0;
 
if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
phoneid = IPC_GET_ARG1(*olddata);
phone_t *phone = &TASK->phones[phoneid];
if (IPC_GET_RETVAL(answer->data) != EOK) {
/*
* The recipient of the cloned phone rejected the offer.
* In this case, the connection was established at the
* request time and therefore we need to slam the phone.
* We don't merely hangup as that would result in
* sending IPC_M_HUNGUP to the third party on the
* other side of the cloned phone.
*/
mutex_lock(&phone->lock);
if (phone->state == IPC_PHONE_CONNECTED) {
spinlock_lock(&phone->callee->lock);
list_remove(&phone->link);
phone->state = IPC_PHONE_SLAMMED;
spinlock_unlock(&phone->callee->lock);
}
mutex_unlock(&phone->lock);
}
} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
if (IPC_GET_RETVAL(answer->data) != EOK) {
/*
* The other party on the cloned phoned rejected our
* request for connection on the protocol level.
* We need to break the connection without sending
* IPC_M_HUNGUP back.
*/
mutex_lock(&phone->lock);
if (phone->state == IPC_PHONE_CONNECTED) {
spinlock_lock(&phone->callee->lock);
list_remove(&phone->link);
phone->state = IPC_PHONE_SLAMMED;
spinlock_unlock(&phone->callee->lock);
}
mutex_unlock(&phone->lock);
}
} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
phoneid = IPC_GET_ARG5(*olddata);
if (IPC_GET_RETVAL(answer->data) != EOK) {
if (IPC_GET_RETVAL(answer->data)) {
/* The connection was not accepted */
phone_dealloc(phoneid);
} else {
239,7 → 196,7
}
} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
/* If the users accepted call, connect */
if (IPC_GET_RETVAL(answer->data) == EOK) {
if (!IPC_GET_RETVAL(answer->data)) {
ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata),
&TASK->answerbox);
}
336,26 → 293,6
return 0;
}
 
static void phones_lock(phone_t *p1, phone_t *p2)
{
if (p1 < p2) {
mutex_lock(&p1->lock);
mutex_lock(&p2->lock);
} else if (p1 > p2) {
mutex_lock(&p2->lock);
mutex_lock(&p1->lock);
} else {
mutex_lock(&p1->lock);
}
}
 
static void phones_unlock(phone_t *p1, phone_t *p2)
{
mutex_unlock(&p1->lock);
if (p1 != p2)
mutex_unlock(&p2->lock);
}
 
/** Called before the request is sent.
*
* @param call Call structure with the request.
371,39 → 308,8
int rc;
 
switch (IPC_GET_METHOD(call->data)) {
case IPC_M_CONNECTION_CLONE: {
phone_t *cloned_phone;
GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
return ENOENT);
phones_lock(cloned_phone, phone);
if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
phone->state != IPC_PHONE_CONNECTED) {
phones_unlock(cloned_phone, phone);
return EINVAL;
}
/*
* We can be pretty sure now that both tasks exist and we are
* connected to them. As we continue to hold the phone locks,
* we are effectively preventing them from finishing their
* potential cleanup.
*/
newphid = phone_alloc(phone->callee->task);
if (newphid < 0) {
phones_unlock(cloned_phone, phone);
return ELIMIT;
}
ipc_phone_connect(&phone->callee->task->phones[newphid],
cloned_phone->callee);
phones_unlock(cloned_phone, phone);
/* Set the new phone for the callee. */
IPC_SET_ARG1(call->data, newphid);
break;
}
case IPC_M_CONNECT_ME:
IPC_SET_ARG5(call->data, (unative_t) phone);
break;
case IPC_M_CONNECT_ME_TO:
newphid = phone_alloc(TASK);
newphid = phone_alloc();
if (newphid < 0)
return ELIMIT;
/* Set arg5 for server */
493,7 → 399,7
int phoneid;
 
if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
phoneid = phone_alloc(TASK);
phoneid = phone_alloc();
if (phoneid < 0) { /* Failed to allocate phone */
IPC_SET_RETVAL(call->data, ELIMIT);
ipc_answer(box, call);
/branches/dynload/kernel/generic/src/ipc/ipc.c
328,10 → 328,12
list_remove(&phone->link);
spinlock_unlock(&box->lock);
 
call = ipc_call_alloc(0);
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
call->flags |= IPC_CALL_DISCARD_ANSWER;
_ipc_call(phone, box, call);
if (phone->state != IPC_PHONE_SLAMMED) {
call = ipc_call_alloc(0);
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
call->flags |= IPC_CALL_DISCARD_ANSWER;
_ipc_call(phone, box, call);
}
}
 
phone->state = IPC_PHONE_HUNGUP;
/branches/dynload/kernel/generic/src/ipc/ipcrsc.c
160,29 → 160,27
return result;
}
 
/** Allocate new phone slot in the specified task.
/** Allocate new phone slot in the current TASK structure.
*
* @param t Task for which to allocate a new phone.
*
* @return New phone handle or -1 if the phone handle limit is
* exceeded.
*/
int phone_alloc(task_t *t)
int phone_alloc(void)
{
int i;
 
spinlock_lock(&t->lock);
spinlock_lock(&TASK->lock);
for (i = 0; i < IPC_MAX_PHONES; i++) {
if (t->phones[i].state == IPC_PHONE_HUNGUP &&
atomic_get(&t->phones[i].active_calls) == 0)
t->phones[i].state = IPC_PHONE_FREE;
if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
atomic_get(&TASK->phones[i].active_calls) == 0)
TASK->phones[i].state = IPC_PHONE_FREE;
 
if (t->phones[i].state == IPC_PHONE_FREE) {
t->phones[i].state = IPC_PHONE_CONNECTING;
if (TASK->phones[i].state == IPC_PHONE_FREE) {
TASK->phones[i].state = IPC_PHONE_CONNECTING;
break;
}
}
spinlock_unlock(&t->lock);
spinlock_unlock(&TASK->lock);
 
if (i == IPC_MAX_PHONES)
return -1;
/branches/dynload/kernel/generic/src/synch/spinlock.c
75,7 → 75,7
#ifdef CONFIG_DEBUG_SPINLOCK
void spinlock_lock_debug(spinlock_t *sl)
{
size_t i = 0;
count_t i = 0;
bool deadlock_reported = false;
 
preemption_disable();
/branches/dynload/kernel/generic/src/synch/futex.c
59,8 → 59,8
static void futex_initialize(futex_t *futex);
 
static futex_t *futex_find(uintptr_t paddr);
static size_t futex_ht_hash(unative_t *key);
static bool futex_ht_compare(unative_t *key, size_t keys, link_t *item);
static index_t futex_ht_hash(unative_t *key);
static bool futex_ht_compare(unative_t *key, count_t keys, link_t *item);
static void futex_ht_remove_callback(link_t *item);
 
/**
288,9 → 288,9
*
* @return Index into futex hash table.
*/
size_t futex_ht_hash(unative_t *key)
index_t futex_ht_hash(unative_t *key)
{
return (*key & (FUTEX_HT_SIZE - 1));
return *key & (FUTEX_HT_SIZE-1);
}
 
/** Compare futex hash table item with a key.
300,7 → 300,7
*
* @return True if the item matches the key. False otherwise.
*/
bool futex_ht_compare(unative_t *key, size_t keys, link_t *item)
bool futex_ht_compare(unative_t *key, count_t keys, link_t *item)
{
futex_t *futex;
 
/branches/dynload/kernel/generic/src/synch/waitq.c
415,7 → 415,7
void _waitq_wakeup_unsafe(waitq_t *wq, wakeup_mode_t mode)
{
thread_t *t;
size_t count = 0;
count_t count = 0;
 
loop:
if (list_empty(&wq->head)) {
/branches/dynload/kernel/generic/src/debug/symtab.c
55,7 → 55,7
int symtab_name_lookup(unative_t addr, char **name)
{
#ifdef CONFIG_SYMTAB
size_t i;
count_t i;
for (i = 1; symbol_table[i].address_le; i++) {
if (addr < uint64_t_le2host(symbol_table[i].address_le))
112,11 → 112,11
* @return Pointer to the part of string that should be completed or NULL.
*
*/
static const char *symtab_search_one(const char *name, size_t *startpos)
static const char *symtab_search_one(const char *name, count_t *startpos)
{
size_t namelen = str_length(name);
count_t namelen = str_length(name);
size_t pos;
count_t pos;
for (pos = *startpos; symbol_table[pos].address_le; pos++) {
const char *curname = symbol_table[pos].symbol_name;
153,8 → 153,8
int symtab_addr_lookup(const char *name, uintptr_t *addr)
{
#ifdef CONFIG_SYMTAB
size_t found = 0;
size_t pos = 0;
count_t found = 0;
count_t pos = 0;
const char *hint;
while ((hint = symtab_search_one(name, &pos))) {
182,7 → 182,7
void symtab_print_search(const char *name)
{
#ifdef CONFIG_SYMTAB
size_t pos = 0;
count_t pos = 0;
while (symtab_search_one(name, &pos)) {
uintptr_t addr = uint64_t_le2host(symbol_table[pos].address_le);
char *realname = symbol_table[pos].symbol_name;
203,7 → 203,7
* @return 0 - nothing found, 1 - success, >1 print duplicates
*
*/
int symtab_compl(char *input, size_t size)
int symtab_compl(char *input, count_t size)
{
#ifdef CONFIG_SYMTAB
const char *name = input;
216,8 → 216,8
if (str_length(name) == 0)
return 0;
size_t found = 0;
size_t pos = 0;
count_t found = 0;
count_t pos = 0;
const char *hint;
char output[MAX_SYMBOL_NAME];
/branches/dynload/kernel/generic/src/ddi/irq.c
99,8 → 99,8
* Hash table operations for cases when we know that
* there will be collisions between different keys.
*/
static size_t irq_ht_hash(unative_t *key);
static bool irq_ht_compare(unative_t *key, size_t keys, link_t *item);
static index_t irq_ht_hash(unative_t *key);
static bool irq_ht_compare(unative_t *key, count_t keys, link_t *item);
static void irq_ht_remove(link_t *item);
 
static hash_table_operations_t irq_ht_ops = {
115,8 → 115,8
* However, there might be still collisions among
* elements with single key (sharing of one IRQ).
*/
static size_t irq_lin_hash(unative_t *key);
static bool irq_lin_compare(unative_t *key, size_t keys, link_t *item);
static index_t irq_lin_hash(unative_t *key);
static bool irq_lin_compare(unative_t *key, count_t keys, link_t *item);
static void irq_lin_remove(link_t *item);
 
static hash_table_operations_t irq_lin_ops = {
126,7 → 126,7
};
 
/** Number of buckets in either of the hash tables. */
static size_t buckets;
static count_t buckets;
 
/** Initialize IRQ subsystem.
*
133,7 → 133,7
* @param inrs Numbers of unique IRQ numbers or INRs.
* @param chains Number of chains in the hash table.
*/
void irq_init(size_t inrs, size_t chains)
void irq_init(count_t inrs, count_t chains)
{
buckets = chains;
/*
298,7 → 298,7
*
* @return Index into the hash table.
*/
size_t irq_ht_hash(unative_t key[])
index_t irq_ht_hash(unative_t key[])
{
inr_t inr = (inr_t) key[KEY_INR];
return inr % buckets;
324,7 → 324,7
*
* @return True on match or false otherwise.
*/
bool irq_ht_compare(unative_t key[], size_t keys, link_t *item)
bool irq_ht_compare(unative_t key[], count_t keys, link_t *item)
{
irq_t *irq = hash_table_get_instance(item, irq_t, link);
inr_t inr = (inr_t) key[KEY_INR];
371,7 → 371,7
*
* @return Index into the hash table.
*/
size_t irq_lin_hash(unative_t key[])
index_t irq_lin_hash(unative_t key[])
{
inr_t inr = (inr_t) key[KEY_INR];
return inr;
397,7 → 397,7
*
* @return True on match or false otherwise.
*/
bool irq_lin_compare(unative_t key[], size_t keys, link_t *item)
bool irq_lin_compare(unative_t key[], count_t keys, link_t *item)
{
irq_t *irq = list_get_instance(item, irq_t, link);
devno_t devno = (devno_t) key[KEY_DEVNO];
/branches/dynload/kernel/generic/src/ddi/ddi.c
97,7 → 97,7
* creating address space area.
*
*/
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, int flags)
static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
{
ASSERT(TASK);
ASSERT((pf % FRAME_SIZE) == 0);
118,9 → 118,9
/* Find the zone of the physical memory */
spinlock_lock(&zones.lock);
size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
count_t znum = find_zone(ADDR2PFN(pf), pages, 0);
if (znum == (size_t) -1) {
if (znum == (count_t) -1) {
/* Frames not found in any zones
* -> assume it is hardware device and allow mapping
*/
242,7 → 242,7
{
return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
(size_t) pages, (int) flags);
(count_t) pages, (int) flags);
}
 
/** Wrapper for SYS_ENABLE_IOSPACE syscall.
/branches/dynload/kernel/generic/src/console/console.c
61,7 → 61,7
/** Kernel log initialized */
static bool klog_inited = false;
/** First kernel log characters */
static size_t klog_start = 0;
static index_t klog_start = 0;
/** Number of valid kernel log characters */
static size_t klog_len = 0;
/** Number of stored (not printed) kernel log characters */
170,10 → 170,10
* @return Number of characters read.
*
*/
size_t gets(indev_t *indev, char *buf, size_t buflen)
count_t gets(indev_t *indev, char *buf, size_t buflen)
{
size_t offset = 0;
size_t count = 0;
count_t count = 0;
buf[offset] = 0;
wchar_t ch;
226,7 → 226,7
if ((klog_stored > 0) && (stdout) && (stdout->op->write)) {
/* Print charaters stored in kernel log */
size_t i;
index_t i;
for (i = klog_len - klog_stored; i < klog_len; i++)
stdout->op->write(stdout, klog[(klog_start + i) % KLOG_LENGTH], silent);
klog_stored = 0;
/branches/dynload/kernel/generic/src/console/cmd.c
513,7 → 513,7
spinlock_lock(&cmd_lock);
link_t *cur;
size_t len = 0;
count_t len = 0;
for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
cmd_info_t *hlp;
hlp = list_get_instance(cur, cmd_info_t, link);
651,7 → 651,7
* call the function.
*/
size_t i;
count_t i;
for (i = 0; i < config.cpu_count; i++) {
if (!cpus[i].active)
continue;
970,7 → 970,7
*/
int cmd_tests(cmd_arg_t *argv)
{
size_t len = 0;
count_t len = 0;
test_t *test;
for (test = tests; test->name != NULL; test++) {
if (str_length(test->name) > len)
/branches/dynload/kernel/generic/src/console/kconsole.c
86,7 → 86,7
LIST_INITIALIZE(cmd_head); /**< Command list. */
 
static wchar_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
static size_t history_pos = 0;
static count_t history_pos = 0;
 
/** Initialize kconsole data structures
*
159,9 → 159,9
}
 
/** Print count times a character */
static void print_cc(wchar_t ch, size_t count)
static void print_cc(wchar_t ch, count_t count)
{
size_t i;
count_t i;
for (i = 0; i < count; i++)
putchar(ch);
}
169,7 → 169,7
/** Try to find a command beginning with prefix */
static const char *cmdtab_search_one(const char *name, link_t **startpos)
{
size_t namelen = str_length(name);
count_t namelen = str_length(name);
spinlock_lock(&cmd_lock);
205,7 → 205,7
{
const char *name = input;
size_t found = 0;
count_t found = 0;
link_t *pos = NULL;
const char *hint;
char output[MAX_CMDLINE];
240,7 → 240,7
{
printf("%s> ", prompt);
size_t position = 0;
count_t position = 0;
wchar_t *current = history[history_pos];
current[0] = 0;
280,7 → 280,7
/* Find the beginning of the word
and copy it to tmp */
size_t beg;
count_t beg;
for (beg = position - 1; (beg > 0) && (!isspace(current[beg]));
beg--);
313,7 → 313,7
/* We have a hint */
size_t off = 0;
size_t i = 0;
count_t i = 0;
while ((ch = str_decode(tmp, &off, STR_NO_LIMIT)) != 0) {
if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE))
break;
542,7 → 542,7
if (str_lcmp(hlp->name, cmdline + start,
max(str_length(hlp->name),
str_nlength(cmdline + start, (size_t) (end - start) - 1))) == 0) {
str_nlength(cmdline + start, (count_t) (end - start) - 1))) == 0) {
cmd = hlp;
break;
}
568,7 → 568,7
*/
bool error = false;
size_t i;
count_t i;
for (i = 0; i < cmd->argc; i++) {
start = end;
if (!parse_argument(cmdline, size, &start, &end)) {
659,7 → 659,7
while (true) {
wchar_t *tmp = clever_readline((char *) prompt, stdin);
size_t len = wstr_length(tmp);
count_t len = wstr_length(tmp);
if (!len)
continue;
/branches/dynload/kernel/generic/src/printf/vprintf.c
46,7 → 46,7
static int vprintf_str_write(const char *str, size_t size, void *data)
{
size_t offset = 0;
size_t chars = 0;
count_t chars = 0;
while (offset < size) {
putchar(str_decode(str, &offset, size));
59,7 → 59,7
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
{
size_t offset = 0;
size_t chars = 0;
count_t chars = 0;
while (offset < size) {
putchar(str[chars]);
73,7 → 73,7
int puts(const char *str)
{
size_t offset = 0;
size_t chars = 0;
count_t chars = 0;
wchar_t uc;
while ((uc = str_decode(str, &offset, STR_NO_LIMIT)) != 0) {
/branches/dynload/kernel/generic/src/printf/vsnprintf.c
82,7 → 82,7
* with the trailing zero => print only a part
* of string
*/
size_t index = 0;
index_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)
{
size_t index = 0;
index_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
/branches/dynload/kernel/generic/src/printf/printf_core.c
174,7 → 174,7
*/
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
212,7 → 212,7
*/
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
255,12 → 255,12
return printf_putstr(nullstr, ps);
 
/* Print leading spaces. */
size_t strw = str_length(str);
count_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
size_t counter = 0;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
302,6 → 302,9
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)
308,7 → 311,7
precision = strw;
/* Left padding */
size_t counter = 0;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
430,7 → 433,7
}
width -= precision + size - number_size;
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
593,7 → 596,7
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
size_t counter = 0; /* Number of characters printed */
count_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
/branches/dynload/kernel/generic/src/proc/task.c
54,8 → 54,6
#include <func.h>
#include <string.h>
#include <syscall/copy.h>
#include <macros.h>
#include <ipc/event.h>
 
/** Spinlock protecting the tasks_tree AVL tree. */
SPINLOCK_INITIALIZE(tasks_lock);
198,14 → 196,7
avltree_insert(&tasks_tree, &ta->tasks_tree_node);
spinlock_unlock(&tasks_lock);
interrupts_restore(ipl);
/*
* Notify about task creation.
*/
if (event_is_subscribed(EVENT_WAIT))
event_notify_3(EVENT_WAIT, TASK_CREATE, LOWER32(ta->taskid),
UPPER32(ta->taskid));
 
return ta;
}
 
238,13 → 229,6
if (atomic_predec(&t->as->refcount) == 0)
as_destroy(t->as);
/*
* Notify about task destruction.
*/
if (event_is_subscribed(EVENT_WAIT))
event_notify_3(EVENT_WAIT, TASK_DESTROY, LOWER32(t->taskid),
UPPER32(t->taskid));
free(t);
TASK = NULL;
}
/branches/dynload/kernel/generic/src/proc/scheduler.c
708,7 → 708,7
continue;
 
spinlock_lock(&cpus[cpu].lock);
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIs "\n",
printf("cpu%u: address=%p, nrdy=%ld, needs_relink=%" PRIc "\n",
cpus[cpu].id, &cpus[cpu], atomic_get(&cpus[cpu].nrdy),
cpus[cpu].needs_relink);
/branches/dynload/kernel/generic/src/lib/string.c
62,10 → 62,10
* the NULL-terminator), size_t
*
* [wide] string length number of CHARACTERS in a [wide] string (excluding
* the NULL-terminator), size_t
* the NULL-terminator), count_t
*
* [wide] string width number of display cells on a monospace display taken
* by a [wide] string, size_t
* by a [wide] string, count_t
*
*
* Overview of string metrics:@n
75,10 → 75,10
* size n size_t number of BYTES in a string (excluding the
* NULL-terminator)
*
* length l size_t number of CHARACTERS in a string (excluding the
* length l count_t number of CHARACTERS in a string (excluding the
* null terminator)
*
* width w size_t number of display cells on a monospace display
* width w count_t number of display cells on a monospace display
* taken by a string
*
*
97,7 → 97,7
*
* pointer (char *, wchar_t *)
* byte offset (size_t)
* character index (size_t)
* character index (count_t)
*
*/
 
309,9 → 309,9
* @return Number of bytes used by the characters.
*
*/
size_t str_lsize(const char *str, size_t max_len)
size_t str_lsize(const char *str, count_t max_len)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (len < max_len) {
337,7 → 337,7
* @return Number of bytes used by the wide characters.
*
*/
size_t wstr_lsize(const wchar_t *str, size_t max_len)
size_t wstr_lsize(const wchar_t *str, count_t max_len)
{
return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
}
349,9 → 349,9
* @return Number of characters in string.
*
*/
size_t str_length(const char *str)
count_t str_length(const char *str)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
367,9 → 367,9
* @return Number of characters in @a str.
*
*/
size_t wstr_length(const wchar_t *wstr)
count_t wstr_length(const wchar_t *wstr)
{
size_t len = 0;
count_t len = 0;
while (*wstr++ != 0)
len++;
385,9 → 385,9
* @return Number of characters in string.
*
*/
size_t str_nlength(const char *str, size_t size)
count_t str_nlength(const char *str, size_t size)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, size) != 0)
404,11 → 404,11
* @return Number of characters in string.
*
*/
size_t wstr_nlength(const wchar_t *str, size_t size)
count_t wstr_nlength(const wchar_t *str, size_t size)
{
size_t len = 0;
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
size_t offset = 0;
count_t len = 0;
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
count_t offset = 0;
while ((offset < limit) && (*str++ != 0)) {
len++;
496,7 → 496,7
* 1 if second smaller.
*
*/
int str_lcmp(const char *s1, const char *s2, size_t max_len)
int str_lcmp(const char *s1, const char *s2, count_t max_len)
{
wchar_t c1 = 0;
wchar_t c2 = 0;
504,7 → 504,7
size_t off1 = 0;
size_t off2 = 0;
size_t len = 0;
count_t len = 0;
 
while (true) {
if (len >= max_len)
615,7 → 615,7
return;
wchar_t ch;
size_t src_idx = 0;
count_t src_idx = 0;
size_t dst_off = 0;
while ((ch = src[src_idx++]) != 0) {
637,7 → 637,7
* @return Pointer to character in @a str or NULL if not found.
*
*/
char *str_chr(const char *str, wchar_t ch)
const char *str_chr(const char *str, wchar_t ch)
{
wchar_t acc;
size_t off = 0;
645,7 → 645,7
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
return (char *) (str + last);
return (str + last);
last = off;
}
666,14 → 666,14
* is out of bounds.
*
*/
bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
{
size_t len = wstr_length(str);
count_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
size_t i;
count_t i;
for (i = len; i + 1 > pos; i--)
str[i + 1] = str[i];
694,14 → 694,14
* is out of bounds.
*
*/
bool wstr_remove(wchar_t *str, size_t pos)
bool wstr_remove(wchar_t *str, count_t pos)
{
size_t len = wstr_length(str);
count_t len = wstr_length(str);
if (pos >= len)
return false;
size_t i;
count_t i;
for (i = pos + 1; i <= len; i++)
str[i - 1] = str[i];
/branches/dynload/kernel/generic/src/lib/sort.c
45,8 → 45,8
 
#define EBUFSIZE 32
 
void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot);
void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot);
void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot);
void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot);
 
/** Quicksort wrapper
*
61,7 → 61,7
* @param cmp Comparator function.
*
*/
void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b))
void qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
{
uint8_t buf_tmp[EBUFSIZE];
uint8_t buf_pivot[EBUFSIZE];
93,7 → 93,7
* @param pivot Pointer to scratch memory buffer e_size bytes long.
*
*/
void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot)
void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot)
{
if (n > 4) {
unsigned int i = 0, j = n - 1;
133,7 → 133,7
* @param cmp Comparator function.
*
*/
void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b))
void bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
{
uint8_t buf_slot[EBUFSIZE];
void * slot = buf_slot;
160,7 → 160,7
* @param slot Pointer to scratch memory buffer e_size bytes long.
*
*/
void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot)
void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot)
{
bool done = false;
void * p;
/branches/dynload/kernel/generic/src/adt/hash_table.c
51,9 → 51,9
* @param max_keys Maximal number of keys needed to identify an item.
* @param op Hash table operations structure.
*/
void hash_table_create(hash_table_t *h, size_t m, size_t max_keys, hash_table_operations_t *op)
void hash_table_create(hash_table_t *h, count_t m, count_t max_keys, hash_table_operations_t *op)
{
size_t i;
index_t i;
 
ASSERT(h);
ASSERT(op);
83,7 → 83,7
*/
void hash_table_insert(hash_table_t *h, unative_t key[], link_t *item)
{
size_t chain;
index_t chain;
ASSERT(item);
ASSERT(h);
107,7 → 107,7
link_t *hash_table_find(hash_table_t *h, unative_t key[])
{
link_t *cur;
size_t chain;
index_t chain;
ASSERT(h);
ASSERT(h->op);
137,9 → 137,9
* @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, unative_t key[], size_t keys)
void hash_table_remove(hash_table_t *h, unative_t key[], count_t keys)
{
size_t chain;
index_t chain;
link_t *cur;
ASSERT(h);
/branches/dynload/kernel/generic/src/adt/btree.c
63,9 → 63,9
static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key);
static btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median);
static btree_node_t *node_combine(btree_node_t *node);
static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx);
static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right);
static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx);
static bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
static bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree);
static bool try_rotation_from_left(btree_node_t *rnode);
137,7 → 137,7
*/
void btree_destroy_subtree(btree_node_t *root)
{
size_t i;
count_t i;
 
if (root->keys) {
for (i = 0; i < root->keys + 1; i++) {
269,7 → 269,7
}
if (node->keys > FILL_FACTOR) {
size_t i;
count_t i;
 
/*
* The key can be immediatelly removed.
285,7 → 285,7
}
} else {
size_t idx;
index_t idx;
btree_node_t *rnode, *parent;
 
/*
335,7 → 335,7
continue;
} else {
void *val;
size_t i;
count_t i;
/*
* Now if the key is smaller than cur->key[i]
442,11 → 442,11
*/
void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree)
{
size_t i;
count_t i;
 
for (i = 0; i < node->keys; i++) {
if (key < node->key[i]) {
size_t j;
count_t j;
for (j = node->keys; j > i; j--) {
node->key[j] = node->key[j - 1];
478,11 → 478,11
*/
void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree)
{
size_t i;
count_t i;
 
for (i = 0; i < node->keys; i++) {
if (key < node->key[i]) {
size_t j;
count_t j;
for (j = node->keys; j > i; j--) {
node->key[j] = node->key[j - 1];
510,7 → 510,7
*/
void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key)
{
size_t i, j;
count_t i, j;
for (i = 0; i < node->keys; i++) {
if (key == node->key[i]) {
538,7 → 538,7
*/
void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key)
{
size_t i, j;
count_t i, j;
for (i = 0; i < node->keys; i++) {
if (key == node->key[i]) {
576,7 → 576,7
btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median)
{
btree_node_t *rnode;
size_t i, j;
count_t i, j;
 
ASSERT(median);
ASSERT(node->keys == BTREE_MAX_KEYS);
603,7 → 603,7
* Copy big keys, values and subtree pointers to the new right sibling.
* If this is an index node, do not copy the median.
*/
i = (size_t) INDEX_NODE(node);
i = (count_t) INDEX_NODE(node);
for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {
rnode->key[j] = node->key[i];
rnode->value[j] = node->value[i];
636,9 → 636,9
*/
btree_node_t *node_combine(btree_node_t *node)
{
size_t idx;
index_t idx;
btree_node_t *rnode;
size_t i;
count_t i;
 
ASSERT(!ROOT_NODE(node));
685,9 → 685,9
*
* @return Index of the key associated with the subtree.
*/
size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right)
{
size_t i;
count_t i;
for (i = 0; i < node->keys + 1; i++) {
if (subtree == node->subtree[i])
706,7 → 706,7
* @param rnode Right sibling.
* @param idx Index of the parent node key that is taking part in the rotation.
*/
void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
{
btree_key_t key;
 
743,7 → 743,7
* @param rnode Right sibling.
* @param idx Index of the parent node key that is taking part in the rotation.
*/
void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx)
void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, index_t idx)
{
btree_key_t key;
 
786,7 → 786,7
*/
bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
{
size_t idx;
index_t idx;
btree_node_t *lnode;
 
/*
833,7 → 833,7
*/
bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)
{
size_t idx;
index_t idx;
btree_node_t *rnode;
 
/*
872,7 → 872,7
*/
bool try_rotation_from_left(btree_node_t *rnode)
{
size_t idx;
index_t idx;
btree_node_t *lnode;
 
/*
907,7 → 907,7
*/
bool try_rotation_from_right(btree_node_t *lnode)
{
size_t idx;
index_t idx;
btree_node_t *rnode;
 
/*
940,7 → 940,7
*/
void btree_print(btree_t *t)
{
size_t i;
count_t i;
int depth = t->root->depth;
link_t head, *cur;
 
/branches/dynload/kernel/generic/src/adt/bitmap.c
54,7 → 54,7
* @param map Address of the memory used to hold the map.
* @param bits Number of bits stored in bitmap.
*/
void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits)
void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, count_t bits)
{
bitmap->map = map;
bitmap->bits = bits;
66,13 → 66,13
* @param start Starting bit.
* @param bits Number of bits to set.
*/
void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits)
void bitmap_set_range(bitmap_t *bitmap, index_t start, count_t bits)
{
size_t i = 0;
size_t aligned_start;
size_t lub; /* leading unaligned bits */
size_t amb; /* aligned middle bits */
size_t tab; /* trailing aligned bits */
index_t i=0;
index_t aligned_start;
count_t lub; /* leading unaligned bits */
count_t amb; /* aligned middle bits */
count_t tab; /* trailing aligned bits */
ASSERT(start + bits <= bitmap->bits);
116,13 → 116,13
* @param start Starting bit.
* @param bits Number of bits to clear.
*/
void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits)
void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits)
{
size_t i = 0;
size_t aligned_start;
size_t lub; /* leading unaligned bits */
size_t amb; /* aligned middle bits */
size_t tab; /* trailing aligned bits */
index_t i=0;
index_t aligned_start;
count_t lub; /* leading unaligned bits */
count_t amb; /* aligned middle bits */
count_t tab; /* trailing aligned bits */
ASSERT(start + bits <= bitmap->bits);
168,9 → 168,9
* @param src Source bitmap.
* @param bits Number of bits to copy.
*/
void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits)
void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits)
{
size_t i;
index_t i;
ASSERT(bits <= dst->bits);
ASSERT(bits <= src->bits);
/branches/dynload/kernel/generic/src/mm/slab.c
156,8 → 156,8
slab_cache_t *cache; /**< Pointer to parent cache. */
link_t link; /**< List of full/partial slabs. */
void *start; /**< Start address of first available item. */
size_t available; /**< Count of available items in this slab. */
size_t nextavail; /**< The index of next available item. */
count_t available; /**< Count of available items in this slab. */
index_t nextavail; /**< The index of next available item. */
} slab_t;
 
#ifdef CONFIG_DEBUG
177,7 → 177,7
slab_t *slab;
size_t fsize;
unsigned int i;
size_t zone = 0;
count_t zone = 0;
data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
if (!data) {
215,7 → 215,7
*
* @return number of freed frames
*/
static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
static count_t slab_space_free(slab_cache_t *cache, slab_t *slab)
{
frame_free(KA2PA(slab->start));
if (! (cache->flags & SLAB_CACHE_SLINSIDE))
243,7 → 243,7
*
* @return Number of freed pages
*/
static size_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
static count_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
{
int freed = 0;
 
371,10 → 371,10
*
* @return Number of freed pages
*/
static size_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
static count_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
{
unsigned int i;
size_t frames = 0;
count_t frames = 0;
 
for (i = 0; i < mag->busy; i++) {
frames += slab_obj_destroy(cache, mag->objs[i], NULL);
649,11 → 649,11
* @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing
* @return Number of freed pages
*/
static size_t _slab_reclaim(slab_cache_t *cache, int flags)
static count_t _slab_reclaim(slab_cache_t *cache, int flags)
{
unsigned int i;
slab_magazine_t *mag;
size_t frames = 0;
count_t frames = 0;
int magcount;
if (cache->flags & SLAB_CACHE_NOMAGAZINE)
771,11 → 771,11
}
 
/* Go through all caches and reclaim what is possible */
size_t slab_reclaim(int flags)
count_t slab_reclaim(int flags)
{
slab_cache_t *cache;
link_t *cur;
size_t frames = 0;
count_t frames = 0;
 
spinlock_lock(&slab_cache_lock);
 
/branches/dynload/kernel/generic/src/mm/frame.c
67,29 → 67,29
*/
mutex_t mem_avail_mtx;
condvar_t mem_avail_cv;
size_t mem_avail_req = 0; /**< Number of frames requested. */
size_t mem_avail_gen = 0; /**< Generation counter. */
count_t mem_avail_req = 0; /**< Number of frames requested. */
count_t mem_avail_gen = 0; /**< Generation counter. */
 
/********************/
/* Helper functions */
/********************/
 
static inline size_t frame_index(zone_t *zone, frame_t *frame)
static inline index_t frame_index(zone_t *zone, frame_t *frame)
{
return (size_t) (frame - zone->frames);
return (index_t) (frame - zone->frames);
}
 
static inline size_t frame_index_abs(zone_t *zone, frame_t *frame)
static inline index_t frame_index_abs(zone_t *zone, frame_t *frame)
{
return (size_t) (frame - zone->frames) + zone->base;
return (index_t) (frame - zone->frames) + zone->base;
}
 
static inline bool frame_index_valid(zone_t *zone, size_t index)
static inline bool frame_index_valid(zone_t *zone, index_t index)
{
return (index < zone->count);
}
 
static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
{
return (frame - zone->frames);
}
120,20 → 120,20
* @return Zone number on success, -1 on error.
*
*/
static size_t zones_insert_zone(pfn_t base, size_t count)
static count_t zones_insert_zone(pfn_t base, count_t count)
{
if (zones.count + 1 == ZONES_MAX) {
printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
return (size_t) -1;
return (count_t) -1;
}
size_t i;
count_t i;
for (i = 0; i < zones.count; i++) {
/* Check for overlap */
if (overlaps(base, count,
zones.info[i].base, zones.info[i].count)) {
printf("Zones overlap!\n");
return (size_t) -1;
return (count_t) -1;
}
if (base < zones.info[i].base)
break;
140,7 → 140,7
}
/* Move other zones up */
size_t j;
count_t j;
for (j = zones.count; j > i; j--) {
zones.info[j] = zones.info[j - 1];
zones.info[j].buddy_system->data =
161,10 → 161,10
*
*/
#ifdef CONFIG_DEBUG
static size_t total_frames_free(void)
static count_t total_frames_free(void)
{
size_t total = 0;
size_t i;
count_t total = 0;
count_t i;
for (i = 0; i < zones.count; i++)
total += zones.info[i].free_count;
184,12 → 184,12
* @return Zone index or -1 if not found.
*
*/
size_t find_zone(pfn_t frame, size_t count, size_t hint)
count_t find_zone(pfn_t frame, count_t count, count_t hint)
{
if (hint >= zones.count)
hint = 0;
size_t i = hint;
count_t i = hint;
do {
if ((zones.info[i].base <= frame)
&& (zones.info[i].base + zones.info[i].count >= frame + count))
200,7 → 200,7
i = 0;
} while (i != hint);
return (size_t) -1;
return (count_t) -1;
}
 
/** @return True if zone can allocate specified order */
220,12 → 220,12
* @param hind Preferred zone.
*
*/
static size_t find_free_zone(uint8_t order, zone_flags_t flags, size_t hint)
static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint)
{
if (hint >= zones.count)
hint = 0;
size_t i = hint;
count_t i = hint;
do {
/*
* Check whether the zone meets the search criteria.
243,7 → 243,7
i = 0;
} while (i != hint);
return (size_t) -1;
return (count_t) -1;
}
 
/**************************/
265,7 → 265,7
frame_t *frame = list_get_instance(child, frame_t, buddy_link);
zone_t *zone = (zone_t *) buddy->data;
size_t index = frame_index(zone, frame);
index_t index = frame_index(zone, frame);
do {
if (zone->frames[index].buddy_order != order)
return &zone->frames[index].buddy_link;
291,7 → 291,7
bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
size_t index;
index_t index;
if (is_left) {
index = (frame_index(zone, frame)) +
(1 << frame->buddy_order);
446,7 → 446,7
* @param frame_idx Frame index relative to zone.
*
*/
static void zone_frame_free(zone_t *zone, size_t frame_idx)
static void zone_frame_free(zone_t *zone, index_t frame_idx)
{
ASSERT(zone_flags_available(zone->flags));
467,7 → 467,7
}
 
/** Return frame from zone. */
static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx)
static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx)
{
ASSERT(frame_idx < zone->count);
return &zone->frames[frame_idx];
474,7 → 474,7
}
 
/** Mark frame in zone unavailable to allocation. */
static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx)
{
ASSERT(zone_flags_available(zone->flags));
503,7 → 503,7
* @param buddy Merged zone buddy.
*
*/
static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1, buddy_system_t *buddy)
static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy)
{
ASSERT(zone_flags_available(zones.info[z1].flags));
ASSERT(zone_flags_available(zones.info[z2].flags));
529,7 → 529,7
+ buddy_conf_size(order));
/* This marks all frames busy */
size_t i;
count_t i;
for (i = 0; i < zones.info[z1].count; i++)
frame_initialize(&zones.info[z1].frames[i]);
599,11 → 599,11
* @param count Old zone frame count.
*
*/
static void return_config_frames(size_t znum, pfn_t pfn, size_t count)
static void return_config_frames(count_t znum, pfn_t pfn, count_t count)
{
ASSERT(zone_flags_available(zones.info[znum].flags));
size_t cframes = SIZE2FRAMES(zone_conf_size(count));
count_t cframes = SIZE2FRAMES(zone_conf_size(count));
if ((pfn < zones.info[znum].base)
|| (pfn >= zones.info[znum].base + zones.info[znum].count))
614,7 → 614,7
frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
ASSERT(!frame->buddy_order);
size_t i;
count_t i;
for (i = 0; i < cframes; i++) {
zones.info[znum].busy_count++;
zone_frame_free(&zones.info[znum],
634,17 → 634,17
* @param count Allocated frames in block.
*
*/
static void zone_reduce_region(size_t znum, pfn_t frame_idx, size_t count)
static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count)
{
ASSERT(zone_flags_available(zones.info[znum].flags));
ASSERT(frame_idx + count < zones.info[znum].count);
uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
ASSERT((size_t) (1 << order) >= count);
ASSERT((count_t) (1 << order) >= count);
/* Reduce all blocks to order 0 */
size_t i;
for (i = 0; i < (size_t) (1 << order); i++) {
count_t i;
for (i = 0; i < (count_t) (1 << order); i++) {
frame_t *frame = &zones.info[znum].frames[i + frame_idx];
frame->buddy_order = 0;
if (!frame->refcount)
653,7 → 653,7
}
/* Free unneeded frames */
for (i = count; i < (size_t) (1 << order); i++)
for (i = count; i < (count_t) (1 << order); i++)
zone_frame_free(&zones.info[znum], i + frame_idx);
}
 
670,7 → 670,7
* The function uses
*
*/
bool zone_merge(size_t z1, size_t z2)
bool zone_merge(count_t z1, count_t z2)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
733,7 → 733,7
zones.info[z2].count);
/* Move zones down */
size_t i;
count_t i;
for (i = z2 + 1; i < zones.count; i++) {
zones.info[i - 1] = zones.info[i];
zones.info[i - 1].buddy_system->data =
758,7 → 758,7
*/
void zone_merge_all(void)
{
size_t i = 0;
count_t i = 0;
while (i < zones.count) {
if (!zone_merge(i, i + 1))
i++;
776,7 → 776,7
* @return Initialized zone.
*
*/
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, size_t count, zone_flags_t flags)
static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags)
{
zone->base = start;
zone->count = count;
799,7 → 799,7
zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
buddy_conf_size(order));
size_t i;
count_t i;
for (i = 0; i < count; i++)
frame_initialize(&zone->frames[i]);
819,7 → 819,7
* @return Size of zone configuration info (in bytes).
*
*/
uintptr_t zone_conf_size(size_t count)
uintptr_t zone_conf_size(count_t count)
{
return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
}
840,7 → 840,7
* @return Zone number or -1 on error.
*
*/
size_t zone_create(pfn_t start, size_t count, pfn_t confframe, zone_flags_t flags)
count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
855,7 → 855,7
/* If confframe is supposed to be inside our zone, then make sure
* it does not span kernel & init
*/
size_t confcount = SIZE2FRAMES(zone_conf_size(count));
count_t confcount = SIZE2FRAMES(zone_conf_size(count));
if ((confframe >= start) && (confframe < start + count)) {
for (; confframe < start + count; confframe++) {
uintptr_t addr = PFN2ADDR(confframe);
868,7 → 868,7
continue;
bool overlap = false;
size_t i;
count_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(init.tasks[i].addr),
886,11 → 886,11
panic("Cannot find configuration data for zone.");
}
size_t znum = zones_insert_zone(start, count);
if (znum == (size_t) -1) {
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (size_t) -1;
return (count_t) -1;
}
buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
898,7 → 898,7
/* If confdata in zone, mark as unavailable */
if ((confframe >= start) && (confframe < start + count)) {
size_t i;
count_t i;
for (i = confframe; i < confframe + confcount; i++)
zone_mark_unavailable(&zones.info[znum],
i - zones.info[znum].base);
911,11 → 911,11
}
/* Non-available zone */
size_t znum = zones_insert_zone(start, count);
if (znum == (size_t) -1) {
count_t znum = zones_insert_zone(start, count);
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
return (size_t) -1;
return (count_t) -1;
}
zone_construct(&zones.info[znum], NULL, start, count, flags);
930,14 → 930,14
/*******************/
 
/** Set parent of frame. */
void frame_set_parent(pfn_t pfn, void *data, size_t hint)
void frame_set_parent(pfn_t pfn, void *data, count_t hint)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
size_t znum = find_zone(pfn, 1, hint);
count_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (size_t) -1);
ASSERT(znum != (count_t) -1);
zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent = data;
946,14 → 946,14
interrupts_restore(ipl);
}
 
void *frame_get_parent(pfn_t pfn, size_t hint)
void *frame_get_parent(pfn_t pfn, count_t hint)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
size_t znum = find_zone(pfn, 1, hint);
count_t znum = find_zone(pfn, 1, hint);
ASSERT(znum != (size_t) -1);
ASSERT(znum != (count_t) -1);
void *res = zone_get_frame(&zones.info[znum],
pfn - zones.info[znum].base)->parent;
973,11 → 973,11
* @return Physical address of the allocated frame.
*
*/
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone)
{
size_t size = ((size_t) 1) << order;
count_t size = ((count_t) 1) << order;
ipl_t ipl;
size_t hint = pzone ? (*pzone) : 0;
count_t hint = pzone ? (*pzone) : 0;
loop:
ipl = interrupts_disable();
986,16 → 986,16
/*
* First, find suitable frame zone.
*/
size_t znum = find_free_zone(order,
count_t znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
size_t freed = slab_reclaim(0);
count_t freed = slab_reclaim(0);
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
1004,7 → 1004,7
znum = find_free_zone(order,
FRAME_TO_ZONE_FLAGS(flags), hint);
if (znum == (size_t) -1) {
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1019,7 → 1019,7
}
}
if (znum == (size_t) -1) {
if (znum == (count_t) -1) {
if (flags & FRAME_ATOMIC) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1027,7 → 1027,7
}
#ifdef CONFIG_DEBUG
size_t avail = total_frames_free();
count_t avail = total_frames_free();
#endif
spinlock_unlock(&zones.lock);
1038,8 → 1038,8
*/
#ifdef CONFIG_DEBUG
printf("Thread %" PRIu64 " waiting for %" PRIs " frames, "
"%" PRIs " available.\n", THREAD->tid, size, avail);
printf("Thread %" PRIu64 " waiting for %" PRIc " frames, "
"%" PRIc " available.\n", THREAD->tid, size, avail);
#endif
mutex_lock(&mem_avail_mtx);
1048,7 → 1048,7
mem_avail_req = min(mem_avail_req, size);
else
mem_avail_req = size;
size_t gen = mem_avail_gen;
count_t gen = mem_avail_gen;
while (gen == mem_avail_gen)
condvar_wait(&mem_avail_cv, &mem_avail_mtx);
1095,9 → 1095,9
* First, find host frame zone for addr.
*/
pfn_t pfn = ADDR2PFN(frame);
size_t znum = find_zone(pfn, 1, NULL);
count_t znum = find_zone(pfn, 1, NULL);
ASSERT(znum != (size_t) -1);
ASSERT(znum != (count_t) -1);
zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
1134,9 → 1134,9
/*
* First, find host frame zone for addr.
*/
size_t znum = find_zone(pfn, 1, NULL);
count_t znum = find_zone(pfn, 1, NULL);
ASSERT(znum != (size_t) -1);
ASSERT(znum != (count_t) -1);
zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
1145,15 → 1145,15
}
 
/** Mark given range unavailable in frame zones. */
void frame_mark_unavailable(pfn_t start, size_t count)
void frame_mark_unavailable(pfn_t start, count_t count)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
size_t i;
count_t i;
for (i = 0; i < count; i++) {
size_t znum = find_zone(start + i, 1, 0);
if (znum == (size_t) -1) /* PFN not found */
count_t znum = find_zone(start + i, 1, 0);
if (znum == (count_t) -1) /* PFN not found */
continue;
zone_mark_unavailable(&zones.info[znum],
1182,7 → 1182,7
frame_mark_unavailable(ADDR2PFN(KA2PA(config.stack_base)),
SIZE2FRAMES(config.stack_size));
size_t i;
count_t i;
for (i = 0; i < init.cnt; i++) {
pfn_t pfn = ADDR2PFN(KA2PA(init.tasks[i].addr));
frame_mark_unavailable(pfn,
1207,7 → 1207,7
spinlock_lock(&zones.lock);
uint64_t total = 0;
size_t i;
count_t i;
for (i = 0; i < zones.count; i++)
total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
1241,7 → 1241,7
* the listing).
*/
size_t i;
count_t i;
for (i = 0;; i++) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
1253,10 → 1253,10
}
uintptr_t base = PFN2ADDR(zones.info[i].base);
size_t count = zones.info[i].count;
count_t count = zones.info[i].count;
zone_flags_t flags = zones.info[i].flags;
size_t free_count = zones.info[i].free_count;
size_t busy_count = zones.info[i].busy_count;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1263,7 → 1263,7
bool available = zone_flags_available(flags);
printf("%-2" PRIs, i);
printf("%-2" PRIc, i);
#ifdef __32_BITS__
printf(" %10p", base);
1273,13 → 1273,13
printf(" %18p", base);
#endif
printf(" %12" PRIs " %c%c%c ", count,
printf(" %12" PRIc " %c%c%c ", count,
available ? 'A' : ' ',
(flags & ZONE_RESERVED) ? 'R' : ' ',
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available)
printf("%12" PRIs " %12" PRIs,
printf("%12" PRIc " %12" PRIc,
free_count, busy_count);
printf("\n");
1291,13 → 1291,13
* @param num Zone base address or zone number.
*
*/
void zone_print_one(size_t num)
void zone_print_one(count_t num)
{
ipl_t ipl = interrupts_disable();
spinlock_lock(&zones.lock);
size_t znum = (size_t) -1;
count_t znum = (count_t) -1;
size_t i;
count_t i;
for (i = 0; i < zones.count; i++) {
if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
znum = i;
1305,7 → 1305,7
}
}
if (znum == (size_t) -1) {
if (znum == (count_t) -1) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
printf("Zone not found.\n");
1314,9 → 1314,9
uintptr_t base = PFN2ADDR(zones.info[i].base);
zone_flags_t flags = zones.info[i].flags;
size_t count = zones.info[i].count;
size_t free_count = zones.info[i].free_count;
size_t busy_count = zones.info[i].busy_count;
count_t count = zones.info[i].count;
count_t free_count = zones.info[i].free_count;
count_t busy_count = zones.info[i].busy_count;
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
1323,9 → 1323,9
bool available = zone_flags_available(flags);
printf("Zone number: %" PRIs "\n", znum);
printf("Zone number: %" PRIc "\n", znum);
printf("Zone base address: %p\n", base);
printf("Zone size: %" PRIs " frames (%" PRIs " KiB)\n", count,
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
SIZE2KB(FRAMES2SIZE(count)));
printf("Zone flags: %c%c%c\n",
available ? 'A' : ' ',
1333,9 → 1333,9
(flags & ZONE_FIRMWARE) ? 'F' : ' ');
if (available) {
printf("Allocated space: %" PRIs " frames (%" PRIs " KiB)\n",
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
printf("Available space: %" PRIs " frames (%" PRIs " KiB)\n",
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
free_count, SIZE2KB(FRAMES2SIZE(free_count)));
}
}
/branches/dynload/kernel/generic/src/mm/as.c
418,8 → 418,8
btree_node_t, leaf_link);
if ((cond = (bool) node->keys)) {
uintptr_t b = node->key[node->keys - 1];
size_t c =
(size_t) node->value[node->keys - 1];
count_t c =
(count_t) node->value[node->keys - 1];
unsigned int i = 0;
if (overlaps(b, c * PAGE_SIZE, area->base,
555,10 → 555,10
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
size_t j;
count_t j;
pte_t *pte;
for (j = 0; j < (size_t) node->value[i]; j++) {
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
788,8 → 788,8
ipl_t ipl;
int page_flags;
uintptr_t *old_frame;
size_t frame_idx;
size_t used_pages;
index_t frame_idx;
count_t used_pages;
/* Flags for the new memory mapping */
page_flags = area_flags_to_page_flags(flags);
827,7 → 827,7
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
used_pages += (size_t) node->value[i];
used_pages += (count_t) node->value[i];
}
}
 
853,10 → 853,10
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
size_t j;
count_t j;
pte_t *pte;
for (j = 0; j < (size_t) node->value[i]; j++) {
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
903,9 → 903,9
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
size_t j;
count_t j;
for (j = 0; j < (size_t) node->value[i]; j++) {
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
 
/* Insert the new mapping */
1397,16 → 1397,16
*
* @return Zero on failure and non-zero on success.
*/
int used_space_insert(as_area_t *a, uintptr_t page, size_t count)
int used_space_insert(as_area_t *a, uintptr_t page, count_t count)
{
btree_node_t *leaf, *node;
size_t pages;
count_t pages;
unsigned int i;
 
ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
ASSERT(count);
 
pages = (size_t) btree_search(&a->used_space, page, &leaf);
pages = (count_t) btree_search(&a->used_space, page, &leaf);
if (pages) {
/*
* We hit the beginning of some used space.
1423,8 → 1423,8
if (node) {
uintptr_t left_pg = node->key[node->keys - 1];
uintptr_t right_pg = leaf->key[0];
size_t left_cnt = (size_t) node->value[node->keys - 1];
size_t right_cnt = (size_t) leaf->value[0];
count_t left_cnt = (count_t) node->value[node->keys - 1];
count_t right_cnt = (count_t) leaf->value[0];
/*
* Examine the possibility that the interval fits
1478,7 → 1478,7
}
} else if (page < leaf->key[0]) {
uintptr_t right_pg = leaf->key[0];
size_t right_cnt = (size_t) leaf->value[0];
count_t right_cnt = (count_t) leaf->value[0];
/*
* Investigate the border case in which the left neighbour does
1513,8 → 1513,8
if (node) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
uintptr_t right_pg = node->key[0];
size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
size_t right_cnt = (size_t) node->value[0];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
count_t right_cnt = (count_t) node->value[0];
/*
* Examine the possibility that the interval fits
1568,7 → 1568,7
}
} else if (page >= leaf->key[leaf->keys - 1]) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
/*
* Investigate the border case in which the right neighbour
1606,8 → 1606,8
if (page < leaf->key[i]) {
uintptr_t left_pg = leaf->key[i - 1];
uintptr_t right_pg = leaf->key[i];
size_t left_cnt = (size_t) leaf->value[i - 1];
size_t right_cnt = (size_t) leaf->value[i];
count_t left_cnt = (count_t) leaf->value[i - 1];
count_t right_cnt = (count_t) leaf->value[i];
 
/*
* The interval fits between left_pg and right_pg.
1665,7 → 1665,7
}
}
 
panic("Inconsistency detected while adding %" PRIs " pages of used "
panic("Inconsistency detected while adding %" PRIc " pages of used "
"space at %p.", count, page);
}
 
1679,16 → 1679,16
*
* @return Zero on failure and non-zero on success.
*/
int used_space_remove(as_area_t *a, uintptr_t page, size_t count)
int used_space_remove(as_area_t *a, uintptr_t page, count_t count)
{
btree_node_t *leaf, *node;
size_t pages;
count_t pages;
unsigned int i;
 
ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
ASSERT(count);
 
pages = (size_t) btree_search(&a->used_space, page, &leaf);
pages = (count_t) btree_search(&a->used_space, page, &leaf);
if (pages) {
/*
* We are lucky, page is the beginning of some interval.
1717,7 → 1717,7
node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
if (node && page < leaf->key[0]) {
uintptr_t left_pg = node->key[node->keys - 1];
size_t left_cnt = (size_t) node->value[node->keys - 1];
count_t left_cnt = (count_t) node->value[node->keys - 1];
 
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
1733,7 → 1733,7
return 1;
} else if (page + count * PAGE_SIZE <
left_pg + left_cnt*PAGE_SIZE) {
size_t new_cnt;
count_t new_cnt;
/*
* The interval is contained in the rightmost
1757,7 → 1757,7
if (page > leaf->key[leaf->keys - 1]) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
 
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
1772,7 → 1772,7
return 1;
} else if (page + count * PAGE_SIZE < left_pg +
left_cnt * PAGE_SIZE) {
size_t new_cnt;
count_t new_cnt;
/*
* The interval is contained in the rightmost
1799,7 → 1799,7
for (i = 1; i < leaf->keys - 1; i++) {
if (page < leaf->key[i]) {
uintptr_t left_pg = leaf->key[i - 1];
size_t left_cnt = (size_t) leaf->value[i - 1];
count_t left_cnt = (count_t) leaf->value[i - 1];
 
/*
* Now the interval is between intervals corresponding
1819,7 → 1819,7
return 1;
} else if (page + count * PAGE_SIZE <
left_pg + left_cnt * PAGE_SIZE) {
size_t new_cnt;
count_t new_cnt;
/*
* The interval is contained in the
1844,7 → 1844,7
}
 
error:
panic("Inconsistency detected while removing %" PRIs " pages of used "
panic("Inconsistency detected while removing %" PRIc " pages of used "
"space from %p.", count, page);
}
 
1943,7 → 1943,7
as_area_t *area = node->value[i];
mutex_lock(&area->lock);
printf("as_area: %p, base=%p, pages=%" PRIs
printf("as_area: %p, base=%p, pages=%" PRIc
" (%p - %p)\n", area, area->base, area->pages,
area->base, area->base + FRAMES2SIZE(area->pages));
mutex_unlock(&area->lock);
/branches/dynload/kernel/generic/src/mm/tlb.c
79,7 → 79,7
* @param count Number of pages, if required by type.
*/
void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid,
uintptr_t page, size_t count)
uintptr_t page, count_t count)
{
unsigned int i;
 
108,7 → 108,7
/*
* Enqueue the message.
*/
size_t idx = cpu->tlb_messages_count++;
index_t idx = cpu->tlb_messages_count++;
cpu->tlb_messages[idx].type = type;
cpu->tlb_messages[idx].asid = asid;
cpu->tlb_messages[idx].page = page;
143,7 → 143,7
tlb_invalidate_type_t type;
asid_t asid;
uintptr_t page;
size_t count;
count_t count;
unsigned int i;
ASSERT(CPU);
/branches/dynload/kernel/generic/src/mm/backend_anon.c
195,7 → 195,7
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t base = node->key[i];
size_t count = (size_t) node->value[i];
count_t count = (count_t) node->value[i];
unsigned int j;
for (j = 0; j < count; j++) {
/branches/dynload/kernel/generic/src/mm/backend_elf.c
82,7 → 82,7
elf_segment_header_t *entry = area->backend_data.segment;
btree_node_t *leaf;
uintptr_t base, frame, page, start_anon;
size_t i;
index_t i;
bool dirty = false;
 
if (!as_area_check_access(area, access))
234,7 → 234,7
elf_header_t *elf = area->backend_data.elf;
elf_segment_header_t *entry = area->backend_data.segment;
uintptr_t base, start_anon;
size_t i;
index_t i;
 
ASSERT((page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) &&
(page < entry->p_vaddr + entry->p_memsz));
304,7 → 304,7
for (i = 0; i < node->keys; i++) {
uintptr_t base = node->key[i];
size_t count = (size_t) node->value[i];
count_t count = (count_t) node->value[i];
unsigned int j;
/*
/branches/dynload/kernel/generic/src/time/clock.c
134,7 → 134,7
timeout_t *h;
timeout_handler_t f;
void *arg;
size_t missed_clock_ticks = CPU->missed_clock_ticks;
count_t missed_clock_ticks = CPU->missed_clock_ticks;
unsigned int i;
 
/*
/branches/dynload/kernel/generic/include/byteorder.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
/** @addtogroup generic
* @{
*/
/** @file
35,47 → 35,48
#ifndef KERN_BYTEORDER_H_
#define KERN_BYTEORDER_H_
 
#include <arch/byteorder.h>
#include <arch/types.h>
 
#if !(defined(__BE__) ^ defined(__LE__))
#error The architecture must be either big-endian or little-endian.
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN))
#error The architecture must be either big-endian or little-endian.
#endif
 
#ifdef __BE__
#ifdef ARCH_IS_BIG_ENDIAN
 
#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/kernel/generic/include/symtab.h
48,7 → 48,7
extern char *symtab_fmt_name_lookup(unative_t addr);
extern int symtab_addr_lookup(const char *name, uintptr_t *addr);
extern void symtab_print_search(const char *name);
extern int symtab_compl(char *input, size_t size);
extern int symtab_compl(char *input, count_t size);
 
#ifdef CONFIG_SYMTAB
 
/branches/dynload/kernel/generic/include/string.h
57,6 → 57,8
 
#define U_CURSOR 0x2588
 
#define U_BOM 0xfeff
 
/**< No size limit constant */
#define STR_NO_LIMIT ((size_t) -1)
 
69,29 → 71,29
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, size_t max_len);
extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
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_length(const char *str);
extern size_t wstr_length(const wchar_t *wstr);
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
 
extern size_t str_nlength(const char *str, size_t size);
extern size_t wstr_nlength(const wchar_t *str, size_t size);
extern count_t str_nlength(const char *str, size_t size);
extern count_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, size_t max_len);
extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
 
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
 
extern char *str_chr(const char *str, wchar_t ch);
extern const char *str_chr(const char *str, wchar_t ch);
 
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 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);
 
#endif
 
/branches/dynload/kernel/generic/include/console/chardev.h
57,11 → 57,11
/** Protects everything below. */
SPINLOCK_DECLARE(lock);
wchar_t buffer[INDEV_BUFLEN];
size_t counter;
count_t counter;
/** Implementation of indev operations. */
indev_operations_t *op;
size_t index;
index_t index;
void *data;
} indev_t;
 
/branches/dynload/kernel/generic/include/console/kconsole.h
77,7 → 77,7
/** Function implementing the command. */
int (* func)(cmd_arg_t *);
/** Number of arguments. */
size_t argc;
count_t argc;
/** Argument vector. */
cmd_arg_t *argv;
/** Function for printing detailed help. */
/branches/dynload/kernel/generic/include/console/console.h
49,7 → 49,7
extern void klog_update(void);
 
extern wchar_t getc(indev_t *indev);
extern size_t gets(indev_t *indev, char *buf, size_t buflen);
extern count_t gets(indev_t *indev, char *buf, size_t buflen);
extern unative_t sys_klog(int fd, const void *buf, size_t size);
 
extern void grab_console(void);
/branches/dynload/kernel/generic/include/ipc/event.h
49,7 → 49,7
/** Method to be used for the notification. */
unative_t method;
/** Counter. */
size_t counter;
count_t counter;
} event_t;
 
extern void event_init(void);
/branches/dynload/kernel/generic/include/ipc/event_types.h
38,15 → 38,9
typedef enum event_type {
EVENT_KLOG = 0,
EVENT_KCONSOLE,
EVENT_WAIT,
EVENT_END
} event_type_t;
 
typedef enum wait_type {
TASK_CREATE = 0,
TASK_DESTROY
} wait_type_t;
 
#endif
 
/** @}
/branches/dynload/kernel/generic/include/ipc/ipc.h
111,25 → 111,6
/* System-specific methods - only through special syscalls
* These methods have special behaviour
*/
/** Clone connection.
*
* The calling task clones one of its phones for the callee.
*
* - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
* - The callee gets the new phone from ARG1.
* - on answer, the callee acknowledges the new connection by sending EOK back
* or the kernel closes it
*/
#define IPC_M_CONNECTION_CLONE 1
/** Protocol for CONNECT - ME
*
* Through this call, the recipient learns about the new cloned connection.
*
* - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
* - on asnwer, the callee acknowledges the new connection by sending EOK back
* or the kernel closes it
*/
#define IPC_M_CONNECT_ME 2
/** Protocol for CONNECT - TO - ME
*
* Calling process asks the callee to create a callback connection,
146,7 → 127,7
* - the allocated phoneid is passed to userspace
* (on the receiving side) as ARG5 of the call.
*/
#define IPC_M_CONNECT_TO_ME 3
#define IPC_M_CONNECT_TO_ME 1
/** Protocol for CONNECT - ME - TO
*
* Calling process asks the callee to create for him a new connection.
164,11 → 145,11
* - recepient may forward message.
*
*/
#define IPC_M_CONNECT_ME_TO 4
#define IPC_M_CONNECT_ME_TO 2
/** This message is sent to answerbox when the phone
* is hung up
*/
#define IPC_M_PHONE_HUNGUP 5
#define IPC_M_PHONE_HUNGUP 3
 
/** Send as_area over IPC.
* - ARG1 - source as_area base address
178,7 → 159,7
* on answer, the recipient must set:
* - ARG1 - dst as_area base adress
*/
#define IPC_M_SHARE_OUT 6
#define IPC_M_SHARE_OUT 4
 
/** Receive as_area over IPC.
* - ARG1 - destination as_area base address
190,7 → 171,7
* - ARG1 - source as_area base address
* - ARG2 - flags that will be used for sharing
*/
#define IPC_M_SHARE_IN 7
#define IPC_M_SHARE_IN 5
 
/** Send data to another address space over IPC.
* - ARG1 - source address space virtual address
201,7 → 182,7
* - ARG1 - final destination address space virtual address
* - ARG2 - final size of data to be copied
*/
#define IPC_M_DATA_WRITE 8
#define IPC_M_DATA_WRITE 6
 
/** Receive data from another address space over IPC.
* - ARG1 - destination virtual address in the source address space
212,13 → 193,13
* - ARG1 - source virtual address in the destination address space
* - ARG2 - final size of data to be copied
*/
#define IPC_M_DATA_READ 9
#define IPC_M_DATA_READ 7
 
/** Debug the recipient.
* - ARG1 - specifies the debug method (from udebug_method_t)
* - other arguments are specific to the debug method
*/
#define IPC_M_DEBUG_ALL 10
#define IPC_M_DEBUG_ALL 8
 
/* Well-known methods */
#define IPC_M_LAST_SYSTEM 511
/branches/dynload/kernel/generic/include/ipc/ipcrsc.h
35,11 → 35,8
#ifndef KERN_IPCRSC_H_
#define KERN_IPCRSC_H_
 
#include <proc/task.h>
#include <ipc/ipc.h>
 
extern call_t * get_call(unative_t callid);
extern int phone_alloc(task_t *t);
extern int phone_alloc(void);
extern void phone_connect(int phoneid, answerbox_t *box);
extern void phone_dealloc(int phoneid);
 
/branches/dynload/kernel/generic/include/config.h
50,7 → 50,7
} init_task_t;
 
typedef struct {
size_t cnt;
count_t cnt;
init_task_t tasks[CONFIG_INIT_TASKS];
} init_t;
 
65,8 → 65,8
} ballocs_t;
 
typedef struct {
size_t cpu_count; /**< Number of processors detected. */
volatile size_t cpu_active; /**< Number of processors that are up and running. */
count_t cpu_count; /**< Number of processors detected. */
volatile count_t cpu_active; /**< Number of processors that are up and running. */
uintptr_t base;
size_t kernel_size; /**< Size of memory in bytes taken by kernel and stack */
/branches/dynload/kernel/generic/include/ddi/irq.h
104,7 → 104,7
/** Top-half pseudocode. */
irq_code_t *code;
/** Counter. */
size_t counter;
count_t counter;
/**
* Link between IRQs that are notifying the same answerbox. The list is
* protected by the answerbox irq_lock.
162,7 → 162,7
SPINLOCK_EXTERN(irq_uspace_hash_table_lock);
extern hash_table_t irq_uspace_hash_table;
 
extern void irq_init(size_t, size_t);
extern void irq_init(count_t, count_t);
extern void irq_initialize(irq_t *);
extern void irq_register(irq_t *);
extern irq_t *irq_dispatch_and_lock(inr_t);
/branches/dynload/kernel/generic/include/mm/slab.h
72,8 → 72,8
 
typedef struct {
link_t link;
size_t busy; /**< Count of full slots in magazine */
size_t size; /**< Number of slots in magazine */
count_t busy; /**< Count of full slots in magazine */
count_t size; /**< Number of slots in magazine */
void *objs[]; /**< Slots in magazine */
} slab_magazine_t;
 
128,7 → 128,7
 
extern void * slab_alloc(slab_cache_t *, int);
extern void slab_free(slab_cache_t *, void *);
extern size_t slab_reclaim(int);
extern count_t slab_reclaim(int);
 
/* slab subsytem initialization */
extern void slab_cache_init(void);
/branches/dynload/kernel/generic/include/mm/frame.h
80,7 → 80,7
#define FRAME_TO_ZONE_FLAGS(frame_flags) 0
 
typedef struct {
size_t refcount; /**< Tracking of shared frames */
count_t refcount; /**< Tracking of shared frames */
uint8_t buddy_order; /**< Buddy system block order */
link_t buddy_link; /**< Link to the next free block inside
one order */
90,10 → 90,10
typedef struct {
pfn_t base; /**< Frame_no of the first frame
in the frames array */
size_t count; /**< Size of zone */
size_t free_count; /**< Number of free frame_t
count_t count; /**< Size of zone */
count_t free_count; /**< Number of free frame_t
structures */
size_t busy_count; /**< Number of busy frame_t
count_t busy_count; /**< Number of busy frame_t
structures */
zone_flags_t flags; /**< Type of the zone */
108,7 → 108,7
*/
typedef struct {
SPINLOCK_DECLARE(lock);
size_t count;
count_t count;
zone_t info[ZONES_MAX];
} zones_t;
 
124,14 → 124,14
return (pfn_t) (addr >> FRAME_WIDTH);
}
 
static inline size_t SIZE2FRAMES(size_t size)
static inline count_t SIZE2FRAMES(size_t size)
{
if (!size)
return 0;
return (size_t) ((size - 1) >> FRAME_WIDTH) + 1;
return (count_t) ((size - 1) >> FRAME_WIDTH) + 1;
}
 
static inline size_t FRAMES2SIZE(size_t frames)
static inline size_t FRAMES2SIZE(count_t frames)
{
return (size_t) (frames << FRAME_WIDTH);
}
156,17 → 156,17
frame_alloc_generic(order, flags, NULL)
 
extern void frame_init(void);
extern void *frame_alloc_generic(uint8_t, frame_flags_t, size_t *);
extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *);
extern void frame_free(uintptr_t);
extern void frame_reference_add(pfn_t);
 
extern size_t find_zone(pfn_t frame, size_t count, size_t hint);
extern size_t zone_create(pfn_t, size_t, pfn_t, zone_flags_t);
extern void *frame_get_parent(pfn_t, size_t);
extern void frame_set_parent(pfn_t, void *, size_t);
extern void frame_mark_unavailable(pfn_t, size_t);
extern uintptr_t zone_conf_size(size_t);
extern bool zone_merge(size_t, size_t);
extern count_t find_zone(pfn_t frame, count_t count, count_t hint);
extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
extern void *frame_get_parent(pfn_t, count_t);
extern void frame_set_parent(pfn_t, void *, count_t);
extern void frame_mark_unavailable(pfn_t, count_t);
extern uintptr_t zone_conf_size(count_t);
extern bool zone_merge(count_t, count_t);
extern void zone_merge_all(void);
extern uint64_t zone_total_size(void);
 
174,7 → 174,7
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(size_t);
extern void zone_print_one(count_t);
 
#endif
 
/branches/dynload/kernel/generic/include/mm/as.h
94,7 → 94,7
* Number of processors on wich is this address space active.
* Protected by asidlock.
*/
size_t cpu_refcount;
count_t cpu_refcount;
/**
* Address space identifier.
* Constant on architectures that do not support ASIDs.
132,7 → 132,7
/** This lock must be acquired only when the as_area lock is held. */
mutex_t lock;
/** This structure can be deallocated if refcount drops to 0. */
size_t refcount;
count_t refcount;
/**
* B+tree containing complete map of anonymous pages of the shared area.
*/
156,7 → 156,7
};
struct { /**< phys_backend members */
uintptr_t base;
size_t frames;
count_t frames;
};
} mem_backend_data_t;
 
175,7 → 175,7
/** Attributes related to the address space area itself. */
int attributes;
/** Size of this area in multiples of PAGE_SIZE. */
size_t pages;
count_t pages;
/** Base address of this area. */
uintptr_t base;
/** Map of used space. */
225,8 → 225,8
extern int as_area_get_flags(as_area_t *area);
extern bool as_area_check_access(as_area_t *area, pf_access_t access);
extern size_t as_area_get_size(uintptr_t base);
extern int used_space_insert(as_area_t *a, uintptr_t page, size_t count);
extern int used_space_remove(as_area_t *a, uintptr_t page, size_t count);
extern int used_space_insert(as_area_t *a, uintptr_t page, count_t count);
extern int used_space_remove(as_area_t *a, uintptr_t page, count_t count);
 
 
/* Interface to be implemented by architectures. */
/branches/dynload/kernel/generic/include/mm/tlb.h
61,7 → 61,7
tlb_invalidate_type_t type; /**< Message type. */
asid_t asid; /**< Address space identifier. */
uintptr_t page; /**< Page address. */
size_t count; /**< Number of pages to invalidate. */
count_t count; /**< Number of pages to invalidate. */
} tlb_shootdown_msg_t;
 
extern void tlb_init(void);
68,7 → 68,7
 
#ifdef CONFIG_SMP
extern void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid,
uintptr_t page, size_t count);
uintptr_t page, count_t count);
extern void tlb_shootdown_finalize(void);
extern void tlb_shootdown_ipi_recv(void);
#else
84,7 → 84,7
 
extern void tlb_invalidate_all(void);
extern void tlb_invalidate_asid(asid_t asid);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt);
#endif
 
/** @}
/branches/dynload/kernel/generic/include/macros.h
83,13 → 83,6
#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))
 
/** Pseudorandom generator
*
* A pretty standard linear congruential pseudorandom
/branches/dynload/kernel/generic/include/proc/scheduler.h
47,7 → 47,7
typedef struct {
SPINLOCK_DECLARE(lock);
link_t rq_head; /**< List of ready threads. */
size_t n; /**< Number of threads in rq_ready. */
count_t n; /**< Number of threads in rq_ready. */
} runq_t;
 
extern atomic_t nrdy;
/branches/dynload/kernel/generic/include/arch.h
56,7 → 56,7
* the base address of the stack.
*/
typedef struct {
size_t preemption_disabled; /**< Preemption disabled counter. */
count_t preemption_disabled; /**< Preemption disabled counter. */
thread_t *thread; /**< Current thread. */
task_t *task; /**< Current task. */
cpu_t *cpu; /**< Executing cpu. */
/branches/dynload/kernel/generic/include/adt/bitmap.h
41,19 → 41,18
 
typedef struct {
uint8_t *map;
size_t bits;
count_t bits;
} bitmap_t;
 
extern void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits);
extern void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits);
extern void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits);
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits);
extern void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, count_t bits);
extern void bitmap_set_range(bitmap_t *bitmap, index_t start, count_t bits);
extern void bitmap_clear_range(bitmap_t *bitmap, index_t start, count_t bits);
extern void bitmap_copy(bitmap_t *dst, bitmap_t *src, count_t bits);
 
static inline int bitmap_get(bitmap_t *bitmap, size_t bit)
static inline int bitmap_get(bitmap_t *bitmap,index_t bit)
{
if(bit >= bitmap->bits)
return 0;
return !! ((bitmap->map)[bit/8] & (1 << (bit & 7)));
}
 
/branches/dynload/kernel/generic/include/adt/hash_table.h
47,7 → 47,7
*
* @return Index into hash table.
*/
size_t (* hash)(unative_t key[]);
index_t (* hash)(unative_t key[]);
/** Hash table item comparison function.
*
56,7 → 56,7
*
* @return true if the keys match, false otherwise.
*/
bool (*compare)(unative_t key[], size_t keys, link_t *item);
bool (*compare)(unative_t key[], count_t keys, link_t *item);
 
/** Hash table item removal callback.
*
68,8 → 68,8
/** Hash table structure. */
typedef struct {
link_t *entry;
size_t entries;
size_t max_keys;
count_t entries;
count_t max_keys;
hash_table_operations_t *op;
} hash_table_t;
 
76,11 → 76,11
#define hash_table_get_instance(item, type, member) \
list_get_instance((item), type, member)
 
extern void hash_table_create(hash_table_t *h, size_t m, size_t max_keys,
extern void hash_table_create(hash_table_t *h, count_t m, count_t max_keys,
hash_table_operations_t *op);
extern void hash_table_insert(hash_table_t *h, unative_t key[], link_t *item);
extern link_t *hash_table_find(hash_table_t *h, unative_t key[]);
extern void hash_table_remove(hash_table_t *h, unative_t key[], size_t keys);
extern void hash_table_remove(hash_table_t *h, unative_t key[], count_t keys);
 
#endif
 
/branches/dynload/kernel/generic/include/adt/btree.h
46,7 → 46,7
/** B-tree node structure. */
typedef struct btree_node {
/** Number of keys. */
size_t keys;
count_t keys;
 
/**
* Keys. We currently support only single keys. Additional room for one
/branches/dynload/kernel/generic/include/adt/fifo.h
59,9 → 59,9
#define FIFO_INITIALIZE_STATIC(name, t, itms) \
struct { \
t fifo[(itms)]; \
size_t items; \
size_t head; \
size_t tail; \
count_t items; \
index_t head; \
index_t tail; \
} name = { \
.items = (itms), \
.head = 0, \
80,9 → 80,9
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \
struct { \
t *fifo; \
size_t items; \
size_t head; \
size_t tail; \
count_t items; \
index_t head; \
index_t tail; \
} name = { \
.fifo = NULL, \
.items = (itms), \
/branches/dynload/kernel/generic/include/synch/spinlock.h
107,7 → 107,7
extern int printf(const char *, ...);
 
#define DEADLOCK_THRESHOLD 100000000
#define DEADLOCK_PROBE_INIT(pname) size_t pname = 0
#define DEADLOCK_PROBE_INIT(pname) count_t pname = 0
#define DEADLOCK_PROBE(pname, value) \
if ((pname)++ > (value)) { \
(pname) = 0; \
/branches/dynload/kernel/generic/include/synch/futex.h
49,7 → 49,7
/** Futex hash table link. */
link_t ht_link;
/** Number of tasks that reference this futex. */
size_t refcount;
count_t refcount;
} futex_t;
 
extern void futex_init(void);
/branches/dynload/kernel/generic/include/synch/rwlock.h
53,7 → 53,7
*/
mutex_t exclusive;
/** Number of readers in critical section. */
size_t readers_in;
count_t readers_in;
} rwlock_t;
 
#define rwlock_write_lock(rwl) \
/branches/dynload/kernel/generic/include/cpu.h
51,18 → 51,18
SPINLOCK_DECLARE(lock);
 
tlb_shootdown_msg_t tlb_messages[TLB_MESSAGE_QUEUE_LEN];
size_t tlb_messages_count;
count_t tlb_messages_count;
context_t saved_context;
 
atomic_t nrdy;
runq_t rq[RQ_COUNT];
volatile size_t needs_relink;
volatile count_t needs_relink;
 
SPINLOCK_DECLARE(timeoutlock);
link_t timeout_active_head;
 
size_t missed_clock_ticks; /**< When system clock loses a tick, it is recorded here
count_t missed_clock_ticks; /**< When system clock loses a tick, it is recorded here
so that clock() can react. This variable is
CPU-local and can be only accessed when interrupts
are disabled. */
/branches/dynload/kernel/generic/include/context.h
45,7 → 45,7
(c)->sp = ((uintptr_t) (stack)) + (size) - SP_DELTA;
#endif /* context_set */
 
extern int context_save_arch(context_t *c) __attribute__ ((returns_twice));
extern int context_save_arch(context_t *c);
extern void context_restore_arch(context_t *c) __attribute__ ((noreturn));
 
/** Save register context.
76,6 → 76,10
* corresponding call to context_save(), the only
* difference being return value.
*
* Note that content of any local variable defined by
* the caller of context_save() is undefined after
* context_restore().
*
* @param c Context structure.
*/
static inline void context_restore(context_t *c)
/branches/dynload/kernel/generic/include/sort.h
40,8 → 40,8
/*
* sorting routines
*/
extern void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b));
extern void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b));
extern void bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b));
extern void qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b));
 
/*
* default sorting comparators
/branches/dynload/kernel/arch/ia64/src/mm/tlb.c
100,7 → 100,7
}
 
 
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
region_register rr;
bool restore_rr = false;
267,7 → 267,7
* @param tr Translation register.
*/
void
itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr)
itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
{
tr_mapping_insert(va, asid, entry, false, tr);
}
281,7 → 281,7
* @param tr Translation register.
*/
void
dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr)
dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
{
tr_mapping_insert(va, asid, entry, true, tr);
}
298,7 → 298,7
*/
void
tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr,
size_t tr)
index_t tr)
{
region_register rr;
bool restore_rr = false;
353,7 → 353,7
*/
void
dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr,
size_t tr)
index_t tr)
{
tlb_entry_t entry;
382,7 → 382,7
* @param page Virtual page address including VRN bits.
* @param width Width of the purge in bits.
*/
void dtr_purge(uintptr_t page, size_t width)
void dtr_purge(uintptr_t page, count_t width)
{
asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width << 2));
}
710,37 → 710,6
page_table_unlock(AS, true);
}
 
/** Data access rights fault handler.
*
* @param vector Interruption vector.
* @param istate Structure with saved interruption state.
*/
void data_access_rights_fault(uint64_t vector, istate_t *istate)
{
region_register rr;
rid_t rid;
uintptr_t va;
pte_t *t;
 
va = istate->cr_ifa; /* faulting address */
rr.word = rr_read(VA2VRN(va));
rid = rr.map.rid;
 
/*
* Assume a write to a read-only page.
*/
page_table_lock(AS, true);
t = page_mapping_find(AS, va);
ASSERT(t && t->p);
ASSERT(!t->w);
if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate, "Page fault at %p.", va);
panic("%s: va=%p, rid=%d, iip=%p.", __func__, va, rid,
istate->cr_iip);
}
page_table_unlock(AS, true);
}
 
/** Page not present fault handler.
*
* @param vector Interruption vector.
/branches/dynload/kernel/arch/ia64/src/mm/page.c
131,7 → 131,7
vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid)
{
region_register rr_save, rr;
size_t vrn;
index_t vrn;
rid_t rid;
vhpt_entry_t *v;
 
176,7 → 176,7
bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v)
{
region_register rr_save, rr;
size_t vrn;
index_t vrn;
rid_t rid;
bool match;
 
223,7 → 223,7
int flags)
{
region_register rr_save, rr;
size_t vrn;
index_t vrn;
rid_t rid;
uint64_t tag;
 
/branches/dynload/kernel/arch/ia64/src/mm/vhpt.c
53,7 → 53,7
void vhpt_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
{
region_register rr_save, rr;
size_t vrn;
index_t vrn;
rid_t rid;
uint64_t tag;
 
/branches/dynload/kernel/arch/ia64/src/ivt.S
536,7 → 536,7
HEAVYWEIGHT_HANDLER 0x5000 page_not_present
HEAVYWEIGHT_HANDLER 0x5100
HEAVYWEIGHT_HANDLER 0x5200
HEAVYWEIGHT_HANDLER 0x5300 data_access_rights_fault
HEAVYWEIGHT_HANDLER 0x5300
HEAVYWEIGHT_HANDLER 0x5400 general_exception
HEAVYWEIGHT_HANDLER 0x5500 disabled_fp_register
HEAVYWEIGHT_HANDLER 0x5600
/branches/dynload/kernel/arch/ia64/include/types.h
54,6 → 54,8
} uint128_t;
 
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
typedef uint64_t pfn_t;
70,6 → 72,8
 
#define PRIp "lx" /**< Format for uintptr_t. */
#define PRIs "lu" /**< Format for size_t. */
#define PRIc "lu" /**< Format for count_t. */
#define PRIi "lu" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dynload/kernel/arch/ia64/include/mm/tlb.h
76,12 → 76,12
extern void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry);
extern void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry);
 
extern void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, size_t tr);
extern void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr);
extern void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr);
extern void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr);
extern void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr);
extern void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr);
 
extern void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, size_t tr);
extern void dtr_purge(uintptr_t page, size_t width);
extern void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr);
extern void dtr_purge(uintptr_t page, count_t width);
 
extern void dtc_pte_copy(pte_t *t);
extern void itc_pte_copy(pte_t *t);
92,7 → 92,6
extern void data_dirty_bit_fault(uint64_t vector, istate_t *istate);
extern void instruction_access_bit_fault(uint64_t vector, istate_t *istate);
extern void data_access_bit_fault(uint64_t vector, istate_t *istate);
extern void data_access_rights_fault(uint64_t vector, istate_t *istate);
extern void page_not_present(uint64_t vector, istate_t *istate);
 
#endif
/branches/dynload/kernel/arch/ia64/include/mm/page.h
240,7 → 240,7
*
* @return Current contents of rr[i].
*/
static inline uint64_t rr_read(size_t i)
static inline uint64_t rr_read(index_t i)
{
uint64_t ret;
ASSERT(i < REGION_REGISTERS);
253,7 → 253,7
* @param i Region register index.
* @param v Value to be written to rr[i].
*/
static inline void rr_write(size_t i, uint64_t v)
static inline void rr_write(index_t i, uint64_t v)
{
ASSERT(i < REGION_REGISTERS);
asm volatile (
/branches/dynload/kernel/arch/ia64/include/atomic.h
52,12 → 52,12
return v;
}
 
static inline uint64_t test_and_set(atomic_t *val)
{
 
static inline uint64_t test_and_set(atomic_t *val) {
uint64_t v;
asm volatile (
"movl %0 = 0x1;;\n"
"movl %0 = 0x01;;\n"
"xchg8 %0 = %1, %0;;\n"
: "=r" (v), "+m" (val->count)
);
65,13 → 65,6
return v;
}
 
static inline void atomic_lock_arch(atomic_t *val)
{
do {
while (val->count)
;
} while (test_and_set(val));
}
 
static inline void atomic_inc(atomic_t *val)
{
/branches/dynload/kernel/arch/ia64/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 ia64
* @{
*/
/** @file
*/
 
#ifndef KERN_ia64_BYTEORDER_H_
#define KERN_ia64_BYTEORDER_H_
 
/* IA-64 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/ia64/Makefile.inc
41,8 → 41,7
LFLAGS += -EL
AFLAGS += -mconstant-gp
 
BITS = 64
ENDIANESS = LE
DEFS += -D__64_BITS__
 
ARCH_SOURCES = \
arch/$(KARCH)/src/start.S \
/branches/dynload/kernel/arch/sparc64/include/atomic.h
123,7 → 123,7
"ldx %0, %2\n"
"brz %2, 0b\n"
"nop\n"
"ba %%xcc, 1b\n"
"ba %xcc, 1b\n"
"nop\n"
"2:\n"
: "+m" (*((uint64_t *) x)), "+r" (tmp1), "+r" (tmp2) : "r" (0)
/branches/dynload/kernel/arch/sparc64/include/mm/tlb.h
322,7 → 322,7
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(size_t entry)
static inline uint64_t itlb_data_access_read(index_t entry)
{
itlb_data_access_addr_t reg;
336,7 → 336,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(size_t entry, uint64_t value)
static inline void itlb_data_access_write(index_t entry, uint64_t value)
{
itlb_data_access_addr_t reg;
353,7 → 353,7
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(size_t entry)
static inline uint64_t dtlb_data_access_read(index_t entry)
{
dtlb_data_access_addr_t reg;
367,7 → 367,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(size_t entry, uint64_t value)
static inline void dtlb_data_access_write(index_t entry, uint64_t value)
{
dtlb_data_access_addr_t reg;
383,7 → 383,7
*
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(size_t entry)
static inline uint64_t itlb_tag_read_read(index_t entry)
{
itlb_tag_read_addr_t tag;
 
398,7 → 398,7
*
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(size_t entry)
static inline uint64_t dtlb_tag_read_read(index_t entry)
{
dtlb_tag_read_addr_t tag;
 
418,7 → 418,7
* @return Current value of specified IMMU TLB Data Access
* Register.
*/
static inline uint64_t itlb_data_access_read(int tlb, size_t entry)
static inline uint64_t itlb_data_access_read(int tlb, index_t entry)
{
itlb_data_access_addr_t reg;
433,7 → 433,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void itlb_data_access_write(int tlb, size_t entry,
static inline void itlb_data_access_write(int tlb, index_t entry,
uint64_t value)
{
itlb_data_access_addr_t reg;
453,7 → 453,7
* @return Current value of specified DMMU TLB Data Access
* Register.
*/
static inline uint64_t dtlb_data_access_read(int tlb, size_t entry)
static inline uint64_t dtlb_data_access_read(int tlb, index_t entry)
{
dtlb_data_access_addr_t reg;
469,7 → 469,7
* @param entry TLB Entry index.
* @param value Value to be written.
*/
static inline void dtlb_data_access_write(int tlb, size_t entry,
static inline void dtlb_data_access_write(int tlb, index_t entry,
uint64_t value)
{
dtlb_data_access_addr_t reg;
488,7 → 488,7
*
* @return Current value of specified IMMU TLB Tag Read Register.
*/
static inline uint64_t itlb_tag_read_read(int tlb, size_t entry)
static inline uint64_t itlb_tag_read_read(int tlb, index_t entry)
{
itlb_tag_read_addr_t tag;
 
505,7 → 505,7
*
* @return Current value of specified DMMU TLB Tag Read Register.
*/
static inline uint64_t dtlb_tag_read_read(int tlb, size_t entry)
static inline uint64_t dtlb_tag_read_read(int tlb, index_t entry)
{
dtlb_tag_read_addr_t tag;
 
/branches/dynload/kernel/arch/sparc64/include/mm/tsb.h
160,9 → 160,9
struct as;
struct pte;
 
extern void tsb_invalidate(struct as *as, uintptr_t page, size_t pages);
extern void itsb_pte_copy(struct pte *t, size_t index);
extern void dtsb_pte_copy(struct pte *t, size_t index, bool ro);
extern void tsb_invalidate(struct as *as, uintptr_t page, count_t pages);
extern void itsb_pte_copy(struct pte *t, index_t index);
extern void dtsb_pte_copy(struct pte *t, index_t index, bool ro);
 
#endif /* !def __ASM__ */
 
/branches/dynload/kernel/arch/sparc64/include/types.h
46,6 → 46,8
typedef unsigned long uint64_t;
 
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
typedef uint64_t pfn_t;
58,9 → 60,11
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t */
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "llx"
#define PRIs "llu"
#define PRIc "llu"
#define PRIi "llu"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
/branches/dynload/kernel/arch/sparc64/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 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 sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_BYTEORDER_H_
#define KERN_sparc64_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/sparc64/include/context.h
39,7 → 39,7
#include <arch/types.h>
#include <align.h>
 
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE)
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE
 
#ifdef context_set
#undef context_set
/branches/dynload/kernel/arch/sparc64/src/asm.S
277,7 → 277,7
*/
.global switch_to_userspace
switch_to_userspace:
save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
flushw
wrpr %g0, 0, %cleanwin ! avoid information leak
 
/branches/dynload/kernel/arch/sparc64/src/mm/tlb.c
54,8 → 54,8
#include <arch/mm/tsb.h>
#endif
 
static void dtlb_pte_copy(pte_t *, size_t, bool);
static void itlb_pte_copy(pte_t *, size_t);
static void dtlb_pte_copy(pte_t *, index_t, bool);
static void itlb_pte_copy(pte_t *, index_t);
static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *);
static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t,
const char *);
130,7 → 130,7
* @param ro If true, the entry will be created read-only, regardless
* of its w field.
*/
void dtlb_pte_copy(pte_t *t, size_t index, bool ro)
void dtlb_pte_copy(pte_t *t, index_t index, bool ro)
{
tlb_tag_access_reg_t tag;
tlb_data_t data;
167,7 → 167,7
* @param t Page Table Entry to be copied.
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
*/
void itlb_pte_copy(pte_t *t, size_t index)
void itlb_pte_copy(pte_t *t, index_t index)
{
tlb_tag_access_reg_t tag;
tlb_data_t data;
200,7 → 200,7
void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate)
{
uintptr_t page_16k = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
size_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
pte_t *t;
 
page_table_lock(AS, true);
245,7 → 245,7
{
uintptr_t page_8k;
uintptr_t page_16k;
size_t index;
index_t index;
pte_t *t;
 
page_8k = (uint64_t) tag.vpn << MMU_PAGE_WIDTH;
309,7 → 309,7
void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
{
uintptr_t page_16k;
size_t index;
index_t index;
pte_t *t;
 
page_16k = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
497,7 → 497,38
dtlb_sfsr_write(0);
}
 
#if defined (US)
#if defined (US3)
/** Invalidates given TLB entry if and only if it is non-locked or global.
*
* @param tlb TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1,
* TLB_ISMALL, TLB_IBIG).
* @param entry Entry index within the given TLB.
*/
static void tlb_invalidate_entry(int tlb, index_t entry)
{
tlb_data_t d;
tlb_tag_read_reg_t t;
if (tlb == TLB_DSMALL || tlb == TLB_DBIG_0 || tlb == TLB_DBIG_1) {
d.value = dtlb_data_access_read(tlb, entry);
if (!d.l || d.g) {
t.value = dtlb_tag_read_read(tlb, entry);
d.v = false;
dtlb_tag_access_write(t.value);
dtlb_data_access_write(tlb, entry, d.value);
}
} else if (tlb == TLB_ISMALL || tlb == TLB_IBIG) {
d.value = itlb_data_access_read(tlb, entry);
if (!d.l || d.g) {
t.value = itlb_tag_read_read(tlb, entry);
d.v = false;
itlb_tag_access_write(t.value);
itlb_data_access_write(tlb, entry, d.value);
}
}
}
#endif
 
/** Invalidate all unlocked ITLB and DTLB entries. */
void tlb_invalidate_all(void)
{
512,6 → 543,7
* be safe to invalidate them as late as now.
*/
 
#if defined (US)
tlb_data_t d;
tlb_tag_read_reg_t t;
 
535,19 → 567,22
}
}
 
}
 
#elif defined (US3)
 
/** Invalidate all unlocked ITLB and DTLB entries. */
void tlb_invalidate_all(void)
{
itlb_demap(TLB_DEMAP_ALL, 0, 0);
dtlb_demap(TLB_DEMAP_ALL, 0, 0);
for (i = 0; i < tlb_ismall_size(); i++)
tlb_invalidate_entry(TLB_ISMALL, i);
for (i = 0; i < tlb_ibig_size(); i++)
tlb_invalidate_entry(TLB_IBIG, i);
for (i = 0; i < tlb_dsmall_size(); i++)
tlb_invalidate_entry(TLB_DSMALL, i);
for (i = 0; i < tlb_dbig_size(); i++)
tlb_invalidate_entry(TLB_DBIG_0, i);
for (i = 0; i < tlb_dbig_size(); i++)
tlb_invalidate_entry(TLB_DBIG_1, i);
#endif
 
}
 
#endif
 
/** Invalidate all ITLB and DTLB entries that belong to specified ASID
* (Context).
*
579,7 → 614,7
* @param page First page which to sweep out from ITLB and DTLB.
* @param cnt Number of ITLB and DTLB entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
unsigned int i;
tlb_context_reg_t pc_save, ctx;
/branches/dynload/kernel/arch/sparc64/src/mm/as.c
89,7 → 89,7
* The count must be calculated with respect to the emualted 16K page
* size.
*/
size_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
count_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
sizeof(tsb_entry_t)) >> FRAME_WIDTH;
frame_free(KA2PA((uintptr_t) as->arch.itsb));
return cnt;
101,7 → 101,7
int as_create_arch(as_t *as, int flags)
{
#ifdef CONFIG_TSB
tsb_invalidate(as, 0, (size_t) -1);
tsb_invalidate(as, 0, (count_t) -1);
#endif
return 0;
}
/branches/dynload/kernel/arch/sparc64/src/mm/tsb.c
50,14 → 50,13
*
* @param as Address space.
* @param page First page to invalidate in TSB.
* @param pages Number of pages to invalidate. Value of (size_t) -1 means the
* @param pages Number of pages to invalidate. Value of (count_t) -1 means the
* whole TSB.
*/
void tsb_invalidate(as_t *as, uintptr_t page, size_t pages)
void tsb_invalidate(as_t *as, uintptr_t page, count_t pages)
{
size_t i0;
size_t i;
size_t cnt;
index_t i0, i;
count_t cnt;
ASSERT(as->arch.itsb && as->arch.dtsb);
64,7 → 63,7
i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK;
ASSERT(i0 < ITSB_ENTRY_COUNT && i0 < DTSB_ENTRY_COUNT);
 
if (pages == (size_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT)
if (pages == (count_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT)
cnt = ITSB_ENTRY_COUNT;
else
cnt = pages * 2;
82,11 → 81,11
* @param t Software PTE.
* @param index Zero if lower 8K-subpage, one if higher 8K subpage.
*/
void itsb_pte_copy(pte_t *t, size_t index)
void itsb_pte_copy(pte_t *t, index_t index)
{
as_t *as;
tsb_entry_t *tsb;
size_t entry;
index_t entry;
 
ASSERT(index <= 1);
128,11 → 127,11
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
* @param ro If true, the mapping is copied read-only.
*/
void dtsb_pte_copy(pte_t *t, size_t index, bool ro)
void dtsb_pte_copy(pte_t *t, index_t index, bool ro)
{
as_t *as;
tsb_entry_t *tsb;
size_t entry;
index_t entry;
ASSERT(index <= 1);
 
/branches/dynload/kernel/arch/sparc64/src/drivers/scr.c
133,11 → 133,11
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5_BE;
visual = VISUAL_RGB_5_6_5;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_BGR_8_8_8_0;
visual = VISUAL_RGB_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
177,11 → 177,11
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5_BE;
visual = VISUAL_RGB_5_6_5;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_BGR_8_8_8_0;
visual = VISUAL_RGB_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
/branches/dynload/kernel/arch/sparc64/src/drivers/pci.c
91,7 → 91,7
return NULL;
 
ofw_upa_reg_t *reg = prop->value;
size_t regs = prop->size / sizeof(ofw_upa_reg_t);
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < SABRE_INTERNAL_REG + 1)
return NULL;
138,7 → 138,7
return NULL;
 
ofw_upa_reg_t *reg = prop->value;
size_t regs = prop->size / sizeof(ofw_upa_reg_t);
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PSYCHO_INTERNAL_REG + 1)
return NULL;
/branches/dynload/kernel/arch/sparc64/src/drivers/fhc.c
71,7 → 71,7
if (!prop || !prop->value)
return NULL;
size_t regs = prop->size / sizeof(ofw_central_reg_t);
count_t regs = prop->size / sizeof(ofw_central_reg_t);
if (regs + 1 < UART_IMAP_REG)
return NULL;
 
/branches/dynload/kernel/arch/sparc64/src/smp/smp.c
61,7 → 61,7
void smp_init(void)
{
ofw_tree_node_t *node;
size_t cnt = 0;
count_t cnt = 0;
if (is_us() || is_us_iii()) {
node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
/branches/dynload/kernel/arch/sparc64/Makefile.inc
40,8 → 40,7
 
LFLAGS += -no-check-sections -N
 
BITS = 64
ENDIANESS = BE
DEFS += -D__64_BITS__
 
ifeq ($(PROCESSOR),us)
DEFS += -DUS
/branches/dynload/kernel/arch/arm32/include/machine_func.h
File deleted
/branches/dynload/kernel/arch/arm32/include/mach/testarm/testarm.h
File deleted
/branches/dynload/kernel/arch/arm32/include/mach/integratorcp/integratorcp.h
File deleted
/branches/dynload/kernel/arch/arm32/include/drivers/gxemul.h
0,0 → 1,71
/*
* Copyright (c) 2007 Michal Kebrt
* 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 arm32gxemul GXemul
* @brief GXemul machine specific parts.
* @ingroup arm32
* @{
*/
/** @file
* @brief GXemul peripheries drivers declarations.
*/
 
#ifndef KERN_arm32_GXEMUL_H_
#define KERN_arm32_GXEMUL_H_
 
/** Last interrupt number (beginning from 0) whose status is probed
* from interrupt controller
*/
#define GXEMUL_IRQC_MAX_IRQ 8
#define GXEMUL_KBD_IRQ 2
#define GXEMUL_TIMER_IRQ 4
 
/** Timer frequency */
#define GXEMUL_TIMER_FREQ 100
 
#define GXEMUL_KBD_ADDRESS 0x10000000
#define GXEMUL_MP_ADDRESS 0x11000000
#define GXEMUL_FB_ADDRESS 0x12000000
#define GXEMUL_RTC_ADDRESS 0x15000000
#define GXEMUL_IRQC_ADDRESS 0x16000000
 
extern void *gxemul_kbd;
extern void *gxemul_rtc;
extern void *gxemul_irqc;
 
#define GXEMUL_HALT_OFFSET 0x010
#define GXEMUL_RTC_FREQ_OFFSET 0x100
#define GXEMUL_MP_MEMSIZE_OFFSET 0x090
#define GXEMUL_RTC_ACK_OFFSET 0x110
 
extern void gxemul_init(void);
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/arm32/include/types.h
53,6 → 53,8
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
67,6 → 69,8
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dynload/kernel/arch/arm32/include/mm/page.h
94,21 → 94,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i))
get_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i))
get_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i), (x))
set_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i), (x))
set_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i), (x))
 
/* Macros for querying the last-level PTE entries. */
#define PTE_VALID_ARCH(pte) \
204,7 → 204,7
* @param pt Level 0 page table.
* @param i Index of the entry to return.
*/
static inline int get_pt_level0_flags(pte_level0_t *pt, size_t i)
static inline int get_pt_level0_flags(pte_level0_t *pt, index_t i)
{
pte_level0_t *p = &pt[i];
int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
219,7 → 219,7
* @param pt Level 1 page table.
* @param i Index of the entry to return.
*/
static inline int get_pt_level1_flags(pte_level1_t *pt, size_t i)
static inline int get_pt_level1_flags(pte_level1_t *pt, index_t i)
{
pte_level1_t *p = &pt[i];
 
244,7 → 244,7
* @param i index of the entry to be changed
* @param flags new flags
*/
static inline void set_pt_level0_flags(pte_level0_t *pt, size_t i, int flags)
static inline void set_pt_level0_flags(pte_level0_t *pt, index_t i, int flags)
{
pte_level0_t *p = &pt[i];
 
272,7 → 272,7
* @param i Index of the entry to be changed.
* @param flags New flags.
*/
static inline void set_pt_level1_flags(pte_level1_t *pt, size_t i, int flags)
static inline void set_pt_level1_flags(pte_level1_t *pt, index_t i, int flags)
{
pte_level1_t *p = &pt[i];
/branches/dynload/kernel/arch/arm32/include/byteorder.h
0,0 → 1,48
/*
* Copyright (c) 2005 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 arm32
* @{
*/
/** @file
* @brief Endianness definitions.
*/
 
#ifndef KERN_arm32_BYTEORDER_H_
#define KERN_arm32_BYTEORDER_H_
 
#ifdef BIG_ENDIAN
#define ARCH_IS_BIG_ENDIAN
#else
#define ARCH_IS_LITTLE_ENDIAN
#endif
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/arm32/include/exception.h
136,13 → 136,6
extern void install_exception_handlers(void);
extern void exception_init(void);
extern void print_istate(istate_t *istate);
extern void reset_exception_entry(void);
extern void irq_exception_entry(void);
extern void fiq_exception_entry(void);
extern void undef_instr_exception_entry(void);
extern void prefetch_abort_exception_entry(void);
extern void data_abort_exception_entry(void);
extern void swi_exception_entry(void);
 
 
#endif
/branches/dynload/kernel/arch/arm32/Makefile.inc
39,15 → 39,12
 
GCC_CFLAGS += -fno-zero-initialized-in-bss
 
BITS = 32
ENDIANESS = LE
DEFS += -D__32_BITS__
 
ARCH_SOURCES = \
arch/$(KARCH)/src/start.S \
arch/$(KARCH)/src/asm.S \
arch/$(KARCH)/src/exc_handler.S \
arch/$(KARCH)/src/arm32.c \
arch/$(KARCH)/src/machine_func.c \
arch/$(KARCH)/src/context.S \
arch/$(KARCH)/src/dummy.S \
arch/$(KARCH)/src/panic.S \
60,16 → 57,5
arch/$(KARCH)/src/mm/frame.c \
arch/$(KARCH)/src/mm/page.c \
arch/$(KARCH)/src/mm/tlb.c \
arch/$(KARCH)/src/mm/page_fault.c
 
ifeq ($(MACHINE),testarm)
ARCH_SOURCES += arch/$(KARCH)/src/mach/testarm/testarm.c
endif
 
ifeq ($(MACHINE),integratorcp)
ARCH_SOURCES += arch/$(KARCH)/src/mach/integratorcp/integratorcp.c
endif
 
ifeq ($(CONFIG_PL050),y)
ARCH_SOURCES += genarch/src/drivers/pl050/pl050.c
endif
arch/$(KARCH)/src/mm/page_fault.c \
arch/$(KARCH)/src/drivers/gxemul.c
/branches/dynload/kernel/arch/arm32/src/machine_func.c
File deleted
/branches/dynload/kernel/arch/arm32/src/exc_handler.S
File deleted
/branches/dynload/kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
File deleted
/branches/dynload/kernel/arch/arm32/src/mach/testarm/testarm.c
File deleted
Property changes:
Deleted: svn:mergeinfo
/branches/dynload/kernel/arch/arm32/src/arm32.c
37,9 → 37,13
#include <config.h>
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
#include <genarch/drivers/dsrln/dsrlnin.h>
#include <genarch/drivers/dsrln/dsrlnout.h>
#include <genarch/srln/srln.h>
#include <sysinfo/sysinfo.h>
#include <console/console.h>
#include <ddi/irq.h>
#include <arch/drivers/gxemul.h>
#include <print.h>
#include <config.h>
#include <interrupt.h>
48,15 → 52,6
#include <macros.h>
#include <string.h>
 
#ifdef MACHINE_testarm
#include <arch/mach/testarm/testarm.h>
#endif
 
#ifdef MACHINE_integratorcp
#include <arch/mach/integratorcp/integratorcp.h>
#endif
 
 
/** Performs arm32-specific initialization before main_bsp() is called. */
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
{
82,7 → 77,7
/** Performs arm32 specific initialization afterr mm is initialized. */
void arch_post_mm_init(void)
{
machine_init();
gxemul_init();
/* Initialize exception dispatch table */
exception_init();
89,10 → 84,18
interrupt_init();
#ifdef CONFIG_FB
machine_fb_init();
fb_properties_t prop = {
.addr = GXEMUL_FB_ADDRESS,
.offset = 0,
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_BGR_8_8_8,
};
fb_init(&prop);
#else
#ifdef CONFIG_ARM_PRN
machine_output_init();
dsrlnout_init((ioport8_t *) gxemul_kbd);
#endif /* CONFIG_ARM_PRN */
#endif /* CONFIG_FB */
}
123,7 → 126,30
*/
void arch_post_smp_init(void)
{
machine_input_init();
#ifdef CONFIG_ARM_KBD
/*
* Initialize the GXemul keyboard port. Then initialize the serial line
* module and connect it to the GXemul keyboard.
*/
dsrlnin_instance_t *dsrlnin_instance
= dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ);
if (dsrlnin_instance) {
srln_instance_t *srln_instance = srln_init();
if (srln_instance) {
indev_t *sink = stdin_wire();
indev_t *srln = srln_wire(srln_instance, sink);
dsrlnin_wire(dsrlnin_instance, srln);
}
}
/*
* This is the necessary evil until the userspace driver is entirely
* self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ);
sysinfo_set_item_val("kbd.address.virtual", NULL, (unative_t) gxemul_kbd);
#endif
}
 
 
130,6 → 156,7
/** Performs arm32 specific tasks needed before the new task is run. */
void before_task_runs_arch(void)
{
tlb_invalidate_all();
}
 
 
141,7 → 168,6
{
uint8_t *stck;
tlb_invalidate_all();
stck = &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA];
supervisor_sp = (uintptr_t) stck;
}
157,7 → 183,8
/** Halts CPU. */
void cpu_halt(void)
{
machine_cpu_halt();
*((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET))
= 0;
}
 
/** Reboot. */
184,7 → 211,6
/** Acquire console back for kernel. */
void arch_grab_console(void)
{
machine_grab_console();
#ifdef CONFIG_FB
fb_redraw();
#endif
193,7 → 219,6
/** Return console to userspace. */
void arch_release_console(void)
{
machine_release_console();
}
 
/** @}
/branches/dynload/kernel/arch/arm32/src/exception.c
39,17 → 39,10
#include <interrupt.h>
#include <arch/mm/page_fault.h>
#include <arch/barrier.h>
#include <arch/drivers/gxemul.h>
#include <print.h>
#include <syscall/syscall.h>
 
#ifdef MACHINE_testarm
#include <arch/mach/testarm/testarm.h>
#endif
 
#ifdef MACHINE_integratorcp
#include <arch/mach/integratorcp/integratorcp.h>
#endif
 
/** Offset used in calculation of exception handler's relative address.
*
* @see install_handler()
65,6 → 58,159
/** Size of memory block occupied by exception vectors. */
#define EXC_VECTORS_SIZE (EXC_VECTORS * 4)
 
/** Switches to kernel stack and saves all registers there.
*
* Temporary exception stack is used to save a few registers
* before stack switch takes place.
*
*/
inline static void setup_stack_and_save_regs()
{
asm volatile (
"ldr r13, =exc_stack\n"
"stmfd r13!, {r0}\n"
"mrs r0, spsr\n"
"and r0, r0, #0x1f\n"
"cmp r0, #0x10\n"
"bne 1f\n"
/* prev mode was usermode */
"ldmfd r13!, {r0}\n"
"ldr r13, =supervisor_sp\n"
"ldr r13, [r13]\n"
"stmfd r13!, {lr}\n"
"stmfd r13!, {r0-r12}\n"
"stmfd r13!, {r13, lr}^\n"
"mrs r0, spsr\n"
"stmfd r13!, {r0}\n"
"b 2f\n"
/* mode was not usermode */
"1:\n"
"stmfd r13!, {r1, r2, r3}\n"
"mrs r1, cpsr\n"
"mov r2, lr\n"
"bic r1, r1, #0x1f\n"
"orr r1, r1, r0\n"
"mrs r0, cpsr\n"
"msr cpsr_c, r1\n"
"mov r3, r13\n"
"stmfd r13!, {r2}\n"
"mov r2, lr\n"
"stmfd r13!, {r4-r12}\n"
"mov r1, r13\n"
/* the following two lines are for debugging */
"mov sp, #0\n"
"mov lr, #0\n"
"msr cpsr_c, r0\n"
"ldmfd r13!, {r4, r5, r6, r7}\n"
"stmfd r1!, {r4, r5, r6}\n"
"stmfd r1!, {r7}\n"
"stmfd r1!, {r2}\n"
"stmfd r1!, {r3}\n"
"mrs r0, spsr\n"
"stmfd r1!, {r0}\n"
"mov r13, r1\n"
"2:\n"
);
}
 
/** Returns from exception mode.
*
* Previously saved state of registers (including control register)
* is restored from the stack.
*/
inline static void load_regs()
{
asm volatile(
"ldmfd r13!, {r0} \n"
"msr spsr, r0 \n"
"and r0, r0, #0x1f \n"
"cmp r0, #0x10 \n"
"bne 1f \n"
 
/* return to user mode */
"ldmfd r13!, {r13, lr}^ \n"
"b 2f \n"
 
/* return to non-user mode */
"1:\n"
"ldmfd r13!, {r1, r2} \n"
"mrs r3, cpsr \n"
"bic r3, r3, #0x1f \n"
"orr r3, r3, r0 \n"
"mrs r0, cpsr \n"
"msr cpsr_c, r3 \n"
 
"mov r13, r1 \n"
"mov lr, r2 \n"
"msr cpsr_c, r0 \n"
 
/* actual return */
"2:\n"
"ldmfd r13, {r0-r12, pc}^\n"
);
}
 
 
/** Switch CPU to mode in which interrupts are serviced (currently it
* is Undefined mode).
*
* The default mode for interrupt servicing (Interrupt Mode)
* can not be used because of nested interrupts (which can occur
* because interrupts are enabled in higher levels of interrupt handler).
*/
inline static void switch_to_irq_servicing_mode()
{
/* switch to Undefined mode */
asm volatile(
/* save regs used during switching */
"stmfd sp!, {r0-r3} \n"
 
/* save stack pointer and link register to r1, r2 */
"mov r1, sp \n"
"mov r2, lr \n"
 
/* mode switch */
"mrs r0, cpsr \n"
"bic r0, r0, #0x1f \n"
"orr r0, r0, #0x1b \n"
"msr cpsr_c, r0 \n"
 
/* restore saved sp and lr */
"mov sp, r1 \n"
"mov lr, r2 \n"
 
/* restore original regs */
"ldmfd sp!, {r0-r3} \n"
);
}
 
/** Calls exception dispatch routine. */
#define CALL_EXC_DISPATCH(exception) \
asm volatile ( \
"mov r0, %[exc]\n" \
"mov r1, r13\n" \
"bl exc_dispatch\n" \
:: [exc] "i" (exception) \
);\
 
/** General exception handler.
*
* Stores registers, dispatches the exception,
* and finally restores registers and returns from exception processing.
*
* @param exception Exception number.
*/
#define PROCESS_EXCEPTION(exception) \
setup_stack_and_save_regs(); \
CALL_EXC_DISPATCH(exception) \
load_regs();
 
/** Updates specified exception vector to jump to given handler.
*
* Addresses of handlers are stored in memory following exception vectors.
86,6 → 232,71
 
}
 
/** Low-level Reset Exception handler. */
static void reset_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_RESET);
}
 
/** Low-level Software Interrupt Exception handler. */
static void swi_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_SWI);
}
 
/** Low-level Undefined Instruction Exception handler. */
static void undef_instr_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_UNDEF_INSTR);
}
 
/** Low-level Fast Interrupt Exception handler. */
static void fiq_exception_entry(void)
{
PROCESS_EXCEPTION(EXC_FIQ);
}
 
/** Low-level Prefetch Abort Exception handler. */
static void prefetch_abort_exception_entry(void)
{
asm volatile (
"sub lr, lr, #4"
);
PROCESS_EXCEPTION(EXC_PREFETCH_ABORT);
}
 
/** Low-level Data Abort Exception handler. */
static void data_abort_exception_entry(void)
{
asm volatile (
"sub lr, lr, #8"
);
PROCESS_EXCEPTION(EXC_DATA_ABORT);
}
 
/** Low-level Interrupt Exception handler.
*
* CPU is switched to Undefined mode before further interrupt processing
* because of possible occurence of nested interrupt exception, which
* would overwrite (and thus spoil) stack pointer.
*/
static void irq_exception_entry(void)
{
asm volatile (
"sub lr, lr, #4"
);
setup_stack_and_save_regs();
switch_to_irq_servicing_mode();
CALL_EXC_DISPATCH(EXC_IRQ)
 
load_regs();
}
 
/** Software Interrupt handler.
*
* Dispatches the syscall.
96,6 → 307,37
istate->r3, istate->r4, istate->r5, istate->r6);
}
 
/** Returns the mask of active interrupts. */
static inline uint32_t gxemul_irqc_get_sources(void)
{
return *((uint32_t *) gxemul_irqc);
}
 
/** Interrupt Exception handler.
*
* Determines the sources of interrupt and calls their handlers.
*/
static void irq_exception(int exc_no, istate_t *istate)
{
uint32_t sources = gxemul_irqc_get_sources();
unsigned int i;
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {
if (sources & (1 << i)) {
irq_t *irq = irq_dispatch_and_lock(i);
if (irq) {
/* The IRQ handler was found. */
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/* Spurious interrupt.*/
printf("cpu%d: spurious interrupt (inum=%d)\n",
CPU->id, i);
}
}
}
}
 
/** Fills exception vectors with appropriate exception handlers. */
void install_exception_handlers(void)
{
142,15 → 384,6
}
#endif
 
/** Interrupt Exception handler.
*
* Determines the sources of interrupt and calls their handlers.
*/
static void irq_exception(int exc_no, istate_t *istate)
{
machine_irq_exception(exc_no, istate);
}
 
/** Initializes exception handling.
*
* Installs low-level exception handlers and then registers
/branches/dynload/kernel/arch/arm32/src/mm/frame.c
35,16 → 35,9
 
#include <mm/frame.h>
#include <arch/mm/frame.h>
#include <arch/drivers/gxemul.h>
#include <config.h>
 
#ifdef MACHINE_testarm
#include <arch/mach/testarm/testarm.h>
#endif
 
#ifdef MACHINE_integratorcp
#include <arch/mach/integratorcp/integratorcp.h>
#endif
 
/** Address of the last frame in the memory. */
uintptr_t last_frame = 0;
 
51,7 → 44,7
/** Creates memory zones. */
void frame_arch_init(void)
{
last_frame = machine_get_memory_size();
last_frame = *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET));
/* All memory as one zone */
zone_create(0, ADDR2PFN(last_frame),
60,8 → 53,6
/* blacklist boot page table */
frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME,
BOOT_PAGE_TABLE_SIZE_IN_FRAMES);
 
machine_frame_init();
}
 
/** Frees the boot page table. */
/branches/dynload/kernel/arch/arm32/src/mm/tlb.c
80,7 → 80,7
* @param page Address of the first page whose entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, size_t cnt)
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, count_t cnt)
{
unsigned int i;
 
/branches/dynload/kernel/arch/arm32/src/interrupt.c
35,21 → 35,16
 
#include <arch/asm.h>
#include <arch/regutils.h>
#include <arch/drivers/gxemul.h>
#include <ddi/irq.h>
#include <ddi/device.h>
#include <interrupt.h>
 
#ifdef MACHINE_testarm
#include <arch/mach/testarm/testarm.h>
#endif
 
#ifdef MACHINE_integratorcp
#include <arch/mach/integratorcp/integratorcp.h>
#endif
 
/** Initial size of a table holding interrupt handlers. */
#define IRQ_COUNT 8
 
static irq_t gxemul_timer_irq;
 
/** Disable interrupts.
*
* @return Old interrupt priority level.
57,7 → 52,7
ipl_t interrupts_disable(void)
{
ipl_t ipl = current_status_reg_read();
 
current_status_reg_control_write(STATUS_REG_IRQ_DISABLED_BIT | ipl);
return ipl;
70,7 → 65,7
ipl_t interrupts_enable(void)
{
ipl_t ipl = current_status_reg_read();
 
current_status_reg_control_write(ipl & ~STATUS_REG_IRQ_DISABLED_BIT);
return ipl;
96,6 → 91,41
return current_status_reg_read();
}
 
/** Starts gxemul Real Time Clock device, which asserts regular interrupts.
*
* @param frequency Interrupts frequency (0 disables RTC).
*/
static void gxemul_timer_start(uint32_t frequency)
{
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_FREQ_OFFSET))
= frequency;
}
 
static irq_ownership_t gxemul_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
/** Timer interrupt handler.
*
* @param irq Interrupt information.
* @param arg Not used.
*/
static void gxemul_timer_irq_handler(irq_t *irq)
{
/*
* We are holding a lock which prevents preemption.
* Release the lock, call clock() and reacquire the lock again.
*/
spinlock_unlock(&irq->lock);
clock();
spinlock_lock(&irq->lock);
/* acknowledge tick */
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_ACK_OFFSET))
= 0;
}
 
/** Initialize basic tables for exception dispatching
* and starts the timer.
*/
102,7 → 132,16
void interrupt_init(void)
{
irq_init(IRQ_COUNT, IRQ_COUNT);
machine_timer_irq_start();
irq_initialize(&gxemul_timer_irq);
gxemul_timer_irq.devno = device_assign_devno();
gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ;
gxemul_timer_irq.claim = gxemul_timer_claim;
gxemul_timer_irq.handler = gxemul_timer_irq_handler;
irq_register(&gxemul_timer_irq);
gxemul_timer_start(GXEMUL_TIMER_FREQ);
}
 
/** @}
/branches/dynload/kernel/arch/arm32/src/drivers/gxemul.c
0,0 → 1,51
/*
* Copyright (c) 2007 Michal Kebrt, Petr Stepan
* 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 arm32gxemul
* @{
*/
/** @file
* @brief GXemul drivers.
*/
 
#include <arch/drivers/gxemul.h>
#include <mm/page.h>
 
void *gxemul_kbd;
void *gxemul_rtc;
void *gxemul_irqc;
 
void gxemul_init(void)
{
gxemul_kbd = (void *) hw_map(GXEMUL_KBD_ADDRESS, PAGE_SIZE);
gxemul_rtc = (void *) hw_map(GXEMUL_RTC_ADDRESS, PAGE_SIZE);
gxemul_irqc = (void *) hw_map(GXEMUL_IRQC_ADDRESS, PAGE_SIZE);
}
 
/** @}
*/
/branches/dynload/kernel/arch/arm32/src/start.S
35,33 → 35,11
.global supervisor_sp
 
kernel_image_start:
 
# initialize Stack pointer for exception modes
mrs r4, cpsr
bic r4, r4, #0x1f
 
#FIQ Mode
orr r3, r4, #0x11
msr cpsr_c, r3
ldr sp, =exc_stack
 
#IRQ Mode
orr r3, r4, #0x12
msr cpsr_c, r3
ldr sp, =exc_stack
 
#ABORT Mode
orr r3, r4, #0x17
msr cpsr_c, r3
ldr sp, =exc_stack
 
#UNDEFINED Mode
orr r3, r4, #0x1b
msr cpsr_c, r3
ldr sp, =exc_stack
 
# switch to supervisor mode
orr r3, r4, #0x13
mrs r3, cpsr
bic r3, r3, #0x1f
orr r3, r3, #0x13
msr cpsr_c, r3
ldr sp, =temp_stack
/branches/dynload/kernel/arch/ppc32/include/types.h
46,6 → 46,8
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
58,9 → 60,11
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t */
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "x"
#define PRIs "u"
#define PRIc "u"
#define PRIi "u"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
/branches/dynload/kernel/arch/ppc32/include/mm/page.h
102,21 → 102,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
 
/* Macros for querying the last-level PTEs. */
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0)
130,7 → 130,7
#include <mm/mm.h>
#include <arch/interrupt.h>
 
static inline int get_pt_flags(pte_t *pt, size_t i)
static inline int get_pt_flags(pte_t *pt, index_t i)
{
pte_t *p = &pt[i];
143,7 → 143,7
(p->global << PAGE_GLOBAL_SHIFT));
}
 
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dynload/kernel/arch/ppc32/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 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 ppc32
* @{
*/
/** @file
*/
 
#ifndef KERN_ppc32_BYTEORDER_H_
#define KERN_ppc32_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/ppc32/Makefile.inc
39,8 → 39,7
AFLAGS += -a32
LFLAGS += -no-check-sections -N
 
BITS = 32
ENDIANESS = BE
DEFS += -D__32_BITS__
 
ARCH_SOURCES = \
arch/$(KARCH)/src/context.S \
/branches/dynload/kernel/arch/ppc32/src/ppc32.c
36,7 → 36,6
#include <arch.h>
#include <arch/boot/boot.h>
#include <genarch/drivers/via-cuda/cuda.h>
#include <genarch/kbrd/kbrd.h>
#include <arch/interrupt.h>
#include <genarch/fb/fb.h>
#include <genarch/fb/visuals.h>
92,10 → 91,10
visual = VISUAL_INDIRECT_8;
break;
case 16:
visual = VISUAL_RGB_5_5_5_BE;
visual = VISUAL_RGB_5_5_5;
break;
case 24:
visual = VISUAL_BGR_8_8_8;
visual = VISUAL_RGB_8_8_8;
break;
case 32:
visual = VISUAL_RGB_0_8_8_8;
118,6 → 117,31
/* Initialize IRQ routing */
irq_init(IRQ_COUNT, IRQ_COUNT);
if (bootinfo.macio.addr) {
/* Initialize PIC */
cir_t cir;
void *cir_arg;
pic_init(bootinfo.macio.addr, PAGE_SIZE, &cir, &cir_arg);
#ifdef CONFIG_VIA_CUDA
uintptr_t pa = bootinfo.macio.addr + 0x16000;
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
size_t offset = pa - aligned_addr;
size_t size = 2 * PAGE_SIZE;
cuda_t *cuda = (cuda_t *)
(hw_map(aligned_addr, offset + size) + offset);
/* Initialize I/O controller */
cuda_instance_t *cuda_instance =
cuda_init(cuda, IRQ_CUDA, cir, cir_arg);
if (cuda_instance) {
indev_t *sink = stdin_wire();
cuda_wire(cuda_instance, sink);
}
#endif
}
/* Merge all zones to 1 big zone */
zone_merge_all();
}
133,35 → 157,6
 
void arch_post_smp_init(void)
{
if (bootinfo.macio.addr) {
/* Initialize PIC */
cir_t cir;
void *cir_arg;
pic_init(bootinfo.macio.addr, PAGE_SIZE, &cir, &cir_arg);
 
#ifdef CONFIG_MAC_KBD
uintptr_t pa = bootinfo.macio.addr + 0x16000;
uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
size_t offset = pa - aligned_addr;
size_t size = 2 * PAGE_SIZE;
cuda_t *cuda = (cuda_t *)
(hw_map(aligned_addr, offset + size) + offset);
/* Initialize I/O controller */
cuda_instance_t *cuda_instance =
cuda_init(cuda, IRQ_CUDA, cir, cir_arg);
if (cuda_instance) {
kbrd_instance_t *kbrd_instance = kbrd_init();
if (kbrd_instance) {
indev_t *sink = stdin_wire();
indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
cuda_wire(cuda_instance, kbrd);
pic_enable_interrupt(IRQ_CUDA);
}
}
#endif
}
}
 
void calibrate_delay_loop(void)
/branches/dynload/kernel/arch/ppc32/src/mm/tlb.c
549,7 → 549,7
}
 
 
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
// TODO
tlb_invalidate_all();
/branches/dynload/kernel/arch/ppc32/src/mm/frame.c
57,7 → 57,7
void frame_arch_init(void)
{
pfn_t minconf = 2;
size_t i;
count_t i;
pfn_t start, conf;
size_t size;
/branches/dynload/kernel/arch/amd64/src/ddi/ddi.c
56,7 → 56,7
*/
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
size_t bits;
count_t bits;
bits = ioaddr + size;
if (bits > IO_PORTS)
98,7 → 98,7
/*
* Enable the range and we are done.
*/
bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
/*
* Increment I/O Permission bitmap generation counter.
117,11 → 117,11
*/
void io_perm_bitmap_install(void)
{
size_t bits;
count_t bits;
ptr_16_64_t cpugdtr;
descriptor_t *gdt_p;
tss_descriptor_t *tss_desc;
size_t ver;
count_t ver;
/* First, copy the I/O Permission Bitmap. */
spinlock_lock(&TASK->lock);
/branches/dynload/kernel/arch/amd64/src/interrupt.c
101,7 → 101,7
static void gp_fault(int n, istate_t *istate)
{
if (TASK) {
size_t ver;
count_t ver;
 
spinlock_lock(&TASK->lock);
ver = TASK->arch.iomapver;
/branches/dynload/kernel/arch/amd64/include/cpu.h
64,7 → 64,7
int stepping;
tss_t *tss;
size_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
struct star_msr {
/branches/dynload/kernel/arch/amd64/include/types.h
46,6 → 46,8
typedef unsigned long long uint64_t;
 
typedef uint64_t size_t;
typedef uint64_t count_t;
typedef uint64_t index_t;
 
typedef uint64_t uintptr_t;
typedef uint64_t pfn_t;
58,9 → 60,11
typedef struct {
} fncptr_t;
 
/**< Formats for uintptr_t, size_t */
/**< Formats for uintptr_t, size_t, count_t and index_t */
#define PRIp "llx"
#define PRIs "llu"
#define PRIc "llu"
#define PRIi "llu"
 
/**< Formats for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t and (u)native_t */
#define PRId8 "d"
/branches/dynload/kernel/arch/amd64/include/atomic.h
115,7 → 115,9
preemption_disable();
asm volatile (
"0:\n"
#ifdef CONFIG_HT
"pause\n"
#endif
"mov %[count], %[tmp]\n"
"testq %[tmp], %[tmp]\n"
"jnz 0b\n" /* lightweight looping on locked spinlock */
/branches/dynload/kernel/arch/amd64/include/mm/page.h
112,33 → 112,33
#define SET_PTL0_ADDRESS_ARCH(ptl0) \
(write_cr3((uintptr_t) (ptl0)))
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
set_pt_addr((pte_t *) (ptl0), (size_t) (i), a)
set_pt_addr((pte_t *) (ptl0), (index_t) (i), a)
#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) \
set_pt_addr((pte_t *) (ptl1), (size_t) (i), a)
set_pt_addr((pte_t *) (ptl1), (index_t) (i), a)
#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) \
set_pt_addr((pte_t *) (ptl2), (size_t) (i), a)
set_pt_addr((pte_t *) (ptl2), (index_t) (i), a)
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
set_pt_addr((pte_t *) (ptl3), (size_t) (i), a)
set_pt_addr((pte_t *) (ptl3), (index_t) (i), a)
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
get_pt_flags((pte_t *) (ptl1), (size_t) (i))
get_pt_flags((pte_t *) (ptl1), (index_t) (i))
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
get_pt_flags((pte_t *) (ptl2), (size_t) (i))
get_pt_flags((pte_t *) (ptl2), (index_t) (i))
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x) \
set_pt_flags((pte_t *) (ptl1), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl1), (index_t) (i), (x))
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) \
set_pt_flags((pte_t *) (ptl2), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl2), (index_t) (i), (x))
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
 
/* Macros for querying the last-level PTE entries. */
#define PTE_VALID_ARCH(p) \
176,7 → 176,7
*/
#define PFERR_CODE_ID (1 << 4)
 
static inline int get_pt_flags(pte_t *pt, size_t i)
static inline int get_pt_flags(pte_t *pt, index_t i)
{
pte_t *p = &pt[i];
189,7 → 189,7
p->global << PAGE_GLOBAL_SHIFT);
}
 
static inline void set_pt_addr(pte_t *pt, size_t i, uintptr_t a)
static inline void set_pt_addr(pte_t *pt, index_t i, uintptr_t a)
{
pte_t *p = &pt[i];
 
197,7 → 197,7
p->addr_32_51 = a >> 32;
}
 
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dynload/kernel/arch/amd64/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 amd64
* @{
*/
/** @file
*/
 
#ifndef KERN_amd64_BYTEORDER_H_
#define KERN_amd64_BYTEORDER_H_
 
/* AMD64 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/amd64/include/proc/task.h
40,7 → 40,7
 
typedef struct {
/** I/O Permission bitmap Generation counter. */
size_t iomapver;
count_t iomapver;
/** I/O Permission bitmap. */
bitmap_t iomap;
} task_arch_t;
/branches/dynload/kernel/arch/amd64/Makefile.inc
41,8 → 41,7
ICC_CFLAGS += $(CMN1)
SUNCC_CFLAGS += -m64 -xmodel=kernel
 
BITS = 64
ENDIANESS = LE
DEFS += -D__64_BITS__
 
## Accepted CPUs
#
/branches/dynload/kernel/arch/mips32/include/elf.h
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup mips32
/** @addtogroup mips32
* @{
*/
/** @file
35,15 → 35,17
#ifndef KERN_mips32_ELF_H_
#define KERN_mips32_ELF_H_
 
#define ELF_MACHINE EM_MIPS
#include <byteorder.h>
 
#ifdef __BE__
#define ELF_DATA_ENCODING ELFDATA2MSB
#define ELF_MACHINE EM_MIPS
 
#ifdef ARCH_IS_BIG_ENDIAN
# define ELF_DATA_ENCODING ELFDATA2MSB
#else
#define ELF_DATA_ENCODING ELFDATA2LSB
# define ELF_DATA_ENCODING ELFDATA2LSB
#endif
 
#define ELF_CLASS ELFCLASS32
#define ELF_CLASS ELFCLASS32
 
#endif
 
/branches/dynload/kernel/arch/mips32/include/mm/page.h
112,21 → 112,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
 
/* Last-level info macros. */
#define PTE_VALID_ARCH(pte) (*((uint32_t *) (pte)) != 0)
140,7 → 140,7
#include <mm/mm.h>
#include <arch/exception.h>
 
static inline int get_pt_flags(pte_t *pt, size_t i)
static inline int get_pt_flags(pte_t *pt, index_t i)
{
pte_t *p = &pt[i];
153,7 → 153,7
(p->g << PAGE_GLOBAL_SHIFT));
}
 
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dynload/kernel/arch/mips32/include/types.h
46,6 → 46,8
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
60,6 → 62,8
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dynload/kernel/arch/mips32/include/arch.h
42,7 → 42,7
 
#include <typedefs.h>
 
extern size_t cpu_count;
extern count_t cpu_count;
 
typedef struct {
uintptr_t addr;
/branches/dynload/kernel/arch/mips32/include/context_offset.h
86,7 → 86,7
#define EOFFSET_STATUS 0x58
#define EOFFSET_EPC 0x5c
#define EOFFSET_K1 0x60
#define REGISTER_SPACE 104 /* respect stack alignment */
#define REGISTER_SPACE 100
 
#ifdef __ASM__
 
/branches/dynload/kernel/arch/mips32/include/atomic.h
88,13 → 88,6
return v;
}
 
static inline void atomic_lock_arch(atomic_t *val) {
do {
while (val->count)
;
} while (test_and_set(val));
}
 
#endif
 
/** @}
/branches/dynload/kernel/arch/mips32/include/byteorder.h
0,0 → 1,47
/*
* Copyright (c) 2005 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 mips32
* @{
*/
/** @file
*/
 
#ifndef KERN_mips32_BYTEORDER_H_
#define KERN_mips32_BYTEORDER_H_
 
#ifdef BIG_ENDIAN
#define ARCH_IS_BIG_ENDIAN
#else
#define ARCH_IS_LITTLE_ENDIAN
#endif
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/mips32/include/debugger.h
53,7 → 53,7
unative_t instruction; /**< Original instruction */
unative_t nextinstruction; /**< Original instruction following break */
int flags; /**< Flags regarding breakpoint */
size_t counter;
count_t counter;
void (*bkfunc)(void *b, istate_t *istate);
} bpinfo_t;
 
/branches/dynload/kernel/arch/mips32/Makefile.inc
36,7 → 36,7
 
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3
 
BITS = 32
DEFS += -D__32_BITS__
 
## Accepted MACHINEs
#
43,18 → 43,15
 
ifeq ($(MACHINE),lgxemul)
BFD_NAME = elf32-tradlittlemips
ENDIANESS = LE
endif
ifeq ($(MACHINE),bgxemul)
BFD_NAME = elf32-tradbigmips
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips
TARGET = mips-linux-gnu
ENDIANESS = BE
GCC_CFLAGS += -D__BE__
GCC_CFLAGS += -DBIG_ENDIAN
endif
ifeq ($(MACHINE),msim)
BFD_NAME = elf32-tradlittlemips
ENDIANESS = LE
GCC_CFLAGS += -mhard-float
endif
 
/branches/dynload/kernel/arch/mips32/src/mips32.c
76,7 → 76,7
/* Stack pointer saved when entering user mode */
uintptr_t supervisor_sp __attribute__ ((section (".text")));
 
size_t cpu_count = 0;
count_t cpu_count = 0;
 
/** Performs mips32-specific initialization before main_bsp() is called. */
void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
84,7 → 84,7
/* Setup usermode */
init.cnt = bootinfo->cnt;
size_t i;
count_t i;
for (i = 0; i < min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS); i++) {
init.tasks[i].addr = bootinfo->tasks[i].addr;
init.tasks[i].size = bootinfo->tasks[i].size;
141,7 → 141,7
.x = 640,
.y = 480,
.scan = 1920,
.visual = VISUAL_RGB_8_8_8,
.visual = VISUAL_BGR_8_8_8,
};
fb_init(&gxemul_prop);
#else
/branches/dynload/kernel/arch/mips32/src/mm/tlb.c
560,7 → 560,7
* @param page First page whose TLB entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
unsigned int i;
ipl_t ipl;
/branches/dynload/kernel/arch/mips32/src/mm/frame.c
62,7 → 62,7
pfn_t count;
} phys_region_t;
 
static size_t phys_regions_count = 0;
static count_t phys_regions_count = 0;
static phys_region_t phys_regions[MAX_REGIONS];
 
/** Check whether frame is available
119,7 → 119,7
/* Init tasks */
bool safe = true;
size_t i;
count_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
174,7 → 174,7
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
 
size_t i;
count_t i;
for (i = 0; i < TLB_ENTRY_COUNT; i++) {
cp0_index_write(i);
tlbwi();
251,7 → 251,7
printf("Base Size\n");
printf("---------- ----------\n");
size_t i;
count_t i;
for (i = 0; i < phys_regions_count; i++) {
printf("%#010x %10u\n",
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
/branches/dynload/kernel/arch/ia32/src/smp/mps.c
86,10 → 86,10
/*
* Implementation of IA-32 SMP configuration interface.
*/
static size_t get_cpu_count(void);
static bool is_cpu_enabled(size_t i);
static bool is_bsp(size_t i);
static uint8_t get_cpu_apic_id(size_t i);
static count_t get_cpu_count(void);
static bool is_cpu_enabled(index_t i);
static bool is_bsp(index_t i);
static uint8_t get_cpu_apic_id(index_t i);
static int mps_irq_to_pin(unsigned int irq);
 
struct smp_config_operations mps_config_operations = {
100,24 → 100,24
.irq_to_pin = mps_irq_to_pin
};
 
size_t get_cpu_count(void)
count_t get_cpu_count(void)
{
return processor_entry_cnt;
}
 
bool is_cpu_enabled(size_t i)
bool is_cpu_enabled(index_t i)
{
ASSERT(i < processor_entry_cnt);
return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
}
 
bool is_bsp(size_t i)
bool is_bsp(index_t i)
{
ASSERT(i < processor_entry_cnt);
return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
}
 
uint8_t get_cpu_apic_id(size_t i)
uint8_t get_cpu_apic_id(index_t i)
{
ASSERT(i < processor_entry_cnt);
return processor_entries[i].l_apic_id;
/branches/dynload/kernel/arch/ia32/src/drivers/vesa.c
85,15 → 85,15
if ((vesa_red_mask == 5) && (vesa_red_pos == 10)
&& (vesa_green_mask == 5) && (vesa_green_pos == 5)
&& (vesa_blue_mask == 5) && (vesa_blue_pos == 0))
visual = VISUAL_RGB_5_5_5_LE;
visual = VISUAL_RGB_5_5_5;
else
visual = VISUAL_RGB_5_6_5_LE;
visual = VISUAL_RGB_5_6_5;
break;
case 24:
visual = VISUAL_BGR_8_8_8;
visual = VISUAL_RGB_8_8_8;
break;
case 32:
visual = VISUAL_BGR_8_8_8_0;
visual = VISUAL_RGB_0_8_8_8;
break;
default:
panic("Unsupported bits per pixel.");
/branches/dynload/kernel/arch/ia32/src/ddi/ddi.c
57,7 → 57,7
*/
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
size_t bits;
count_t bits;
 
bits = ioaddr + size;
if (bits > IO_PORTS)
99,7 → 99,7
/*
* Enable the range and we are done.
*/
bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, (size_t) size);
bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
 
/*
* Increment I/O Permission bitmap generation counter.
118,10 → 118,10
*/
void io_perm_bitmap_install(void)
{
size_t bits;
count_t bits;
ptr_16_32_t cpugdtr;
descriptor_t *gdt_p;
size_t ver;
count_t ver;
 
/* First, copy the I/O Permission Bitmap. */
spinlock_lock(&TASK->lock);
/branches/dynload/kernel/arch/ia32/src/interrupt.c
101,7 → 101,7
static void gp_fault(int n __attribute__((unused)), istate_t *istate)
{
if (TASK) {
size_t ver;
count_t ver;
spinlock_lock(&TASK->lock);
ver = TASK->arch.iomapver;
/branches/dynload/kernel/arch/ia32/src/mm/tlb.c
59,7 → 59,7
* @param page Address of the first page whose entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, size_t cnt)
void tlb_invalidate_pages(asid_t asid __attribute__((unused)), uintptr_t page, count_t cnt)
{
unsigned int i;
 
/branches/dynload/kernel/arch/ia32/src/mm/frame.c
70,7 → 70,7
#endif
pfn_t pfn;
size_t count;
count_t count;
if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
/* To be safe, make available zone possibly smaller */
/branches/dynload/kernel/arch/ia32/src/atomic.S
42,7 → 42,9
movl 12(%esp),%ebx
 
0:
#ifdef CONFIG_HT
pause # Pentium 4's with HT love this instruction
#endif
movl (%ebx),%eax
testl %eax,%eax
jnz 0b # lightweight looping while it is locked
/branches/dynload/kernel/arch/ia32/include/atomic.h
114,7 → 114,9
preemption_disable();
asm volatile (
"0:\n"
#ifdef CONFIG_HT
"pause\n" /* Pentium 4's HT love this instruction */
#endif
"mov %[count], %[tmp]\n"
"testl %[tmp], %[tmp]\n"
"jnz 0b\n" /* lightweight looping on locked spinlock */
/branches/dynload/kernel/arch/ia32/include/cpu.h
57,7 → 57,7
unsigned int stepping;
tss_t *tss;
size_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */
} cpu_arch_t;
 
#endif
/branches/dynload/kernel/arch/ia32/include/types.h
46,6 → 46,8
typedef unsigned long long uint64_t;
 
typedef uint32_t size_t;
typedef uint32_t count_t;
typedef uint32_t index_t;
 
typedef uint32_t uintptr_t;
typedef uint32_t pfn_t;
60,6 → 62,8
 
#define PRIp "x" /**< Format for uintptr_t. */
#define PRIs "u" /**< Format for size_t. */
#define PRIc "u" /**< Format for count_t. */
#define PRIi "u" /**< Format for index_t. */
 
#define PRId8 "d" /**< Format for int8_t. */
#define PRId16 "d" /**< Format for int16_t. */
/branches/dynload/kernel/arch/ia32/include/mm/page.h
95,21 → 95,21
 
/* Get PTE flags accessors for each level. */
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_flags((pte_t *) (ptl0), (size_t) (i))
get_pt_flags((pte_t *) (ptl0), (index_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
PAGE_PRESENT
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
PAGE_PRESENT
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_flags((pte_t *) (ptl3), (size_t) (i))
get_pt_flags((pte_t *) (ptl3), (index_t) (i))
 
/* Set PTE flags accessors for each level. */
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl0), (index_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
 
/* Macros for querying the last level entries. */
#define PTE_VALID_ARCH(p) \
145,7 → 145,7
/** When bit on this position is 1, a reserved bit was set in page directory. */
#define PFERR_CODE_RSVD (1 << 3)
 
static inline int get_pt_flags(pte_t *pt, size_t i)
static inline int get_pt_flags(pte_t *pt, index_t i)
{
pte_t *p = &pt[i];
158,7 → 158,7
p->global << PAGE_GLOBAL_SHIFT);
}
 
static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
{
pte_t *p = &pt[i];
/branches/dynload/kernel/arch/ia32/include/smp/smp.h
39,10 → 39,10
 
/** SMP config opertaions interface. */
struct smp_config_operations {
size_t (* cpu_count)(void); /**< Return number of detected processors. */
bool (* cpu_enabled)(size_t i); /**< Check whether the processor of index i is enabled. */
bool (*cpu_bootstrap)(size_t i); /**< Check whether the processor of index i is BSP. */
uint8_t (*cpu_apic_id)(size_t i); /**< Return APIC ID of the processor of index i. */
count_t (* cpu_count)(void); /**< Return number of detected processors. */
bool (* cpu_enabled)(index_t i); /**< Check whether the processor of index i is enabled. */
bool (*cpu_bootstrap)(index_t i); /**< Check whether the processor of index i is BSP. */
uint8_t (*cpu_apic_id)(index_t i); /**< Return APIC ID of the processor of index i. */
int (*irq_to_pin)(unsigned int irq); /**< Return mapping between irq and APIC pin. */
};
 
/branches/dynload/kernel/arch/ia32/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 ia32
* @{
*/
/** @file
*/
 
#ifndef KERN_ia32_BYTEORDER_H_
#define KERN_ia32_BYTEORDER_H_
 
/* IA-32 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/kernel/arch/ia32/include/proc/task.h
40,7 → 40,7
 
typedef struct {
/** I/O Permission bitmap Generation counter. */
size_t iomapver;
count_t iomapver;
/** I/O Permission bitmap. */
bitmap_t iomap;
} task_arch_t;
/branches/dynload/kernel/arch/ia32/Makefile.inc
35,8 → 35,7
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686
 
BITS = 32
ENDIANESS = LE
DEFS += -D__32_BITS__
 
CMN1 = -m32
GCC_CFLAGS += $(CMN1)
/branches/dynload/kernel/test/avltree/avltree1.c
194,7 → 194,7
return node;
}
 
static void test_tree_insert(avltree_t *tree, size_t node_count)
static void test_tree_insert(avltree_t *tree, count_t node_count)
{
unsigned int i;
avltree_node_t *newnode;
201,7 → 201,7
avltree_create(tree);
TPRINTF("Inserting %" PRIs " nodes...", node_count);
TPRINTF("Inserting %" PRIc " nodes...", node_count);
for (i = 0; i < node_count; i++) {
newnode = alloc_avltree_node();
214,7 → 214,7
TPRINTF("done.\n");
}
 
static void test_tree_delete(avltree_t *tree, size_t node_count,
static void test_tree_delete(avltree_t *tree, count_t node_count,
int node_position)
{
avltree_node_t *delnode;
245,7 → 245,7
TPRINTF("done.\n");
}
 
static void test_tree_delmin(avltree_t *tree, size_t node_count)
static void test_tree_delmin(avltree_t *tree, count_t node_count)
{
unsigned int i = 0;
/branches/dynload/kernel/test/synch/rwlock4.c
148,7 → 148,7
thread_t *thrd;
context_save(&ctx);
TPRINTF("sp=%#x, readers_in=%" PRIs "\n", ctx.sp, rwlock.readers_in);
TPRINTF("sp=%#x, readers_in=%" PRIc "\n", ctx.sp, rwlock.readers_in);
TPRINTF("Creating %" PRIu32 " readers\n", rd);
for (i = 0; i < rd; i++) {
/branches/dynload/kernel/test/mm/falloc2.c
52,7 → 52,7
{
int order, run, allocated, i;
uint8_t val = THREAD->tid % THREADS;
size_t k;
index_t k;
void **frames = (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC);
if (frames == NULL) {
82,9 → 82,9
TPRINTF("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id);
for (i = 0; i < allocated; i++) {
for (k = 0; k <= (((size_t) FRAME_SIZE << order) - 1); k++) {
for (k = 0; k <= (((index_t) FRAME_SIZE << order) - 1); k++) {
if (((uint8_t *) frames[i])[k] != val) {
TPRINTF("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIs "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
TPRINTF("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %#" PRIi "\n", THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
atomic_inc(&thread_fail);
goto cleanup;
}
/branches/dynload/kernel/test/mm/purge1.c
37,7 → 37,7
#include <debug.h>
 
extern void tlb_invalidate_all(void);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t va, size_t cnt);
extern void tlb_invalidate_pages(asid_t asid, uintptr_t va, count_t cnt);
 
char *test_purge1(void)
{
/branches/dynload/kernel/genarch/include/kbrd/scanc_mac.h
File deleted
/branches/dynload/kernel/genarch/include/kbrd/scanc_pl050.h
File deleted
/branches/dynload/kernel/genarch/include/drivers/pl050/pl050.h
File deleted
/branches/dynload/kernel/genarch/include/drivers/via-cuda/cuda.h
38,80 → 38,14
#include <ddi/irq.h>
#include <arch/types.h>
#include <console/chardev.h>
#include <synch/spinlock.h>
 
typedef struct {
uint8_t b;
uint8_t pad0[0x1ff];
 
uint8_t a;
uint8_t pad1[0x1ff];
 
uint8_t dirb;
uint8_t pad2[0x1ff];
 
uint8_t dira;
uint8_t pad3[0x1ff];
 
uint8_t t1cl;
uint8_t pad4[0x1ff];
 
uint8_t t1ch;
uint8_t pad5[0x1ff];
 
uint8_t t1ll;
uint8_t pad6[0x1ff];
 
uint8_t t1lh;
uint8_t pad7[0x1ff];
 
uint8_t t2cl;
uint8_t pad8[0x1ff];
 
uint8_t t2ch;
uint8_t pad9[0x1ff];
 
uint8_t sr;
uint8_t pad10[0x1ff];
 
uint8_t acr;
uint8_t pad11[0x1ff];
 
uint8_t pcr;
uint8_t pad12[0x1ff];
 
uint8_t ifr;
uint8_t pad13[0x1ff];
 
uint8_t ier;
uint8_t pad14[0x1ff];
 
uint8_t anh;
uint8_t pad15[0x1ff];
} cuda_t;
 
enum {
CUDA_RCV_BUF_SIZE = 5
};
 
enum cuda_xfer_state {
cx_listen,
cx_receive,
cx_rcv_end,
cx_send_start,
cx_send
};
 
typedef struct {
irq_t irq;
cuda_t *cuda;
indev_t *kbrdin;
uint8_t rcv_buf[CUDA_RCV_BUF_SIZE];
uint8_t snd_buf[CUDA_RCV_BUF_SIZE];
size_t bidx;
size_t snd_bytes;
enum cuda_xfer_state xstate;
SPINLOCK_DECLARE(dev_lock);
} cuda_instance_t;
 
extern cuda_instance_t *cuda_init(cuda_t *, inr_t, cir_t, void *);
/branches/dynload/kernel/genarch/include/fb/visuals.h
35,20 → 35,17
#ifndef KERN_VISUALS_H_
#define KERN_VISUALS_H_
 
typedef enum {
VISUAL_INDIRECT_8,
VISUAL_RGB_5_5_5_LE,
VISUAL_RGB_5_5_5_BE,
VISUAL_RGB_5_6_5_LE,
VISUAL_RGB_5_6_5_BE,
VISUAL_BGR_8_8_8,
VISUAL_BGR_0_8_8_8,
VISUAL_BGR_8_8_8_0,
VISUAL_RGB_8_8_8,
VISUAL_RGB_0_8_8_8,
VISUAL_RGB_8_8_8_0
} visual_t;
#define VISUAL_INDIRECT_8 0
 
#define VISUAL_RGB_5_5_5 1
#define VISUAL_RGB_5_6_5 2
#define VISUAL_RGB_8_8_8 3
#define VISUAL_RGB_8_8_8_0 4
#define VISUAL_RGB_0_8_8_8 5
 
#define VISUAL_BGR_0_8_8_8 6
#define VISUAL_BGR_8_8_8 7
 
#endif
 
/** @}
/branches/dynload/kernel/genarch/Makefile.inc
110,18 → 110,6
genarch/src/kbrd/scanc_sun.c
endif
 
ifeq ($(CONFIG_PL050),y)
GENARCH_SOURCES += \
genarch/src/kbrd/kbrd_pl050.c \
genarch/src/kbrd/scanc_pl050.c
endif
 
ifeq ($(CONFIG_MAC_KBD),y)
GENARCH_SOURCES += \
genarch/src/kbrd/kbrd.c \
genarch/src/kbrd/scanc_mac.c
endif
 
ifeq ($(CONFIG_SRLN),y)
GENARCH_SOURCES += \
genarch/src/srln/srln.c
/branches/dynload/kernel/genarch/src/kbrd/scanc_mac.c
File deleted
/branches/dynload/kernel/genarch/src/kbrd/kbrd_pl050.c
File deleted
/branches/dynload/kernel/genarch/src/kbrd/scanc_pl050.c
File deleted
/branches/dynload/kernel/genarch/src/kbrd/kbrd.c
45,10 → 45,6
#include <genarch/kbrd/scanc_sun.h>
#endif
 
#ifdef CONFIG_MAC_KBD
#include <genarch/kbrd/scanc_mac.h>
#endif
 
#include <synch/spinlock.h>
#include <console/chardev.h>
#include <console/console.h>
/branches/dynload/kernel/genarch/src/fb/fb.c
50,7 → 50,6
#include <string.h>
#include <ddi/ddi.h>
#include <arch/types.h>
#include <byteorder.h>
 
SPINLOCK_INITIALIZE(fb_lock);
 
81,9 → 80,9
#define FG_COLOR 0xffff00
#define INV_COLOR 0xaaaaaa
 
#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
 
#define COL2X(col) ((col) * FONT_WIDTH)
#define ROW2Y(row) ((row) * FONT_SCANLINES)
98,79 → 97,69
 
static void (*rgb_conv)(void *, uint32_t);
 
/*
* RGB conversion functions.
 
/** ARGB 8:8:8:8 conversion
*
* These functions write an RGB value to some memory in some predefined format.
* The naming convention corresponds to the format created by these functions.
* The functions use the so called network order (i.e. big endian) with respect
* to their names.
*/
 
static void rgb_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
(RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
*((uint32_t *) dst) = rgb & 0xffffff;
}
 
 
/** ABGR 8:8:8:8 conversion
*
*/
static void bgr_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
(BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
}
 
static void rgb_8880(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
(GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
}
 
static void bgr_8880(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
(GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
}
 
/** RGB 8:8:8 conversion
*
*/
static void rgb_888(void *dst, uint32_t rgb)
{
((uint8_t *) dst)[0] = RED(rgb, 8);
((uint8_t *) dst)[0] = BLUE(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = BLUE(rgb, 8);
((uint8_t *) dst)[2] = RED(rgb, 8);
}
 
 
/** BGR 8:8:8 conversion
*
*/
static void bgr_888(void *dst, uint32_t rgb)
{
((uint8_t *) dst)[0] = BLUE(rgb, 8);
((uint8_t *) dst)[0] = RED(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = RED(rgb, 8);
((uint8_t *) dst)[2] = BLUE(rgb, 8);
}
 
static void rgb_555_be(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
}
 
static void rgb_555_le(void *dst, uint32_t rgb)
/** RGB 5:5:5 conversion
*
*/
static void rgb_555(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
*((uint16_t *) dst)
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
}
 
static void rgb_565_be(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
}
 
static void rgb_565_le(void *dst, uint32_t rgb)
/** RGB 5:6:5 conversion
*
*/
static void rgb_565(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
*((uint16_t *) dst)
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
}
 
 
/** BGR 3:2:3
/** RGB 3:2:3
*
* Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
* will most likely use a color palette. The color appearance
187,7 → 176,7
* 0 and 255 to other colors.
*
*/
static void bgr_323(void *dst, uint32_t rgb)
static void rgb_323(void *dst, uint32_t rgb)
{
*((uint8_t *) dst)
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
461,25 → 450,17
{
switch (props->visual) {
case VISUAL_INDIRECT_8:
rgb_conv = bgr_323;
rgb_conv = rgb_323;
pixelbytes = 1;
break;
case VISUAL_RGB_5_5_5_LE:
rgb_conv = rgb_555_le;
case VISUAL_RGB_5_5_5:
rgb_conv = rgb_555;
pixelbytes = 2;
break;
case VISUAL_RGB_5_5_5_BE:
rgb_conv = rgb_555_be;
case VISUAL_RGB_5_6_5:
rgb_conv = rgb_565;
pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5_LE:
rgb_conv = rgb_565_le;
pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5_BE:
rgb_conv = rgb_565_be;
pixelbytes = 2;
break;
case VISUAL_RGB_8_8_8:
rgb_conv = rgb_888;
pixelbytes = 3;
489,7 → 470,7
pixelbytes = 3;
break;
case VISUAL_RGB_8_8_8_0:
rgb_conv = rgb_8880;
rgb_conv = rgb_888;
pixelbytes = 4;
break;
case VISUAL_RGB_0_8_8_8:
500,10 → 481,6
rgb_conv = bgr_0888;
pixelbytes = 4;
break;
case VISUAL_BGR_8_8_8_0:
rgb_conv = bgr_8880;
pixelbytes = 4;
break;
default:
panic("Unsupported visual.");
}
/branches/dynload/kernel/genarch/src/ofw/ebus.c
49,7 → 49,7
{
ofw_tree_property_t *prop;
ofw_ebus_range_t *range;
size_t ranges;
count_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
91,7 → 91,7
return false;
 
ofw_ebus_intr_map_t *intr_map = prop->value;
size_t count = prop->size / sizeof(ofw_ebus_intr_map_t);
count_t count = prop->size / sizeof(ofw_ebus_intr_map_t);
ASSERT(count);
/branches/dynload/kernel/genarch/src/ofw/fhc.c
46,7 → 46,7
{
ofw_tree_property_t *prop;
ofw_fhc_range_t *range;
size_t ranges;
count_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
88,7 → 88,7
ofw_tree_property_t *prop;
ofw_central_range_t *range;
size_t ranges;
count_t ranges;
prop = ofw_tree_getprop(node, "ranges");
if (!prop)
/branches/dynload/kernel/genarch/src/ofw/ofw_tree.c
247,8 → 247,7
{
char buf[NAME_BUF_LEN + 1];
ofw_tree_node_t *node = ofw_root;
size_t i;
size_t j;
index_t i, j;
if (path[0] != '/')
return NULL;
/branches/dynload/kernel/genarch/src/ofw/pci.c
54,7 → 54,7
{
ofw_tree_property_t *prop;
ofw_pci_range_t *range;
size_t ranges;
count_t ranges;
 
prop = ofw_tree_getprop(node, "ranges");
if (!prop) {
97,7 → 97,7
ofw_tree_property_t *prop;
ofw_pci_reg_t *assigned_address;
size_t assigned_addresses;
count_t assigned_addresses;
prop = ofw_tree_getprop(node, "assigned-addresses");
if (!prop)
/branches/dynload/kernel/genarch/src/ofw/sbus.c
43,7 → 43,7
{
ofw_tree_property_t *prop;
ofw_sbus_range_t *range;
size_t ranges;
count_t ranges;
/*
* The SBUS support is very rudimentary in that we simply assume
/branches/dynload/kernel/genarch/src/drivers/pl050/pl050.c
File deleted
/branches/dynload/kernel/genarch/src/drivers/via-cuda/cuda.c
1,6 → 1,5
/*
* Copyright (c) 2006 Martin Decky
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
39,53 → 38,16
#include <arch/asm.h>
#include <mm/slab.h>
#include <ddi/device.h>
#include <synch/spinlock.h>
 
static irq_ownership_t cuda_claim(irq_t *irq);
static void cuda_irq_handler(irq_t *irq);
static irq_ownership_t cuda_claim(irq_t *irq)
{
return IRQ_DECLINE;
}
 
static void cuda_irq_listen(irq_t *irq);
static void cuda_irq_receive(irq_t *irq);
static void cuda_irq_rcv_end(irq_t *irq, void *buf, size_t *len);
static void cuda_irq_send_start(irq_t *irq);
static void cuda_irq_send(irq_t *irq);
static void cuda_irq_handler(irq_t *irq)
{
}
 
static void cuda_packet_handle(cuda_instance_t *instance, uint8_t *buf, size_t len);
static void cuda_send_start(cuda_instance_t *instance);
static void cuda_autopoll_set(cuda_instance_t *instance, bool enable);
 
/** B register fields */
enum {
TREQ = 0x08,
TACK = 0x10,
TIP = 0x20
};
 
/** IER register fields */
enum {
IER_CLR = 0x00,
IER_SET = 0x80,
 
SR_INT = 0x04,
ALL_INT = 0x7f
};
 
/** ACR register fields */
enum {
SR_OUT = 0x10
};
 
/** Packet types */
enum {
PT_ADB = 0x00,
PT_CUDA = 0x01
};
 
/** CUDA packet types */
enum {
CPT_AUTOPOLL = 0x01
};
 
cuda_instance_t *cuda_init(cuda_t *dev, inr_t inr, cir_t cir, void *cir_arg)
{
cuda_instance_t *instance
93,15 → 55,7
if (instance) {
instance->cuda = dev;
instance->kbrdin = NULL;
instance->xstate = cx_listen;
instance->bidx = 0;
instance->snd_bytes = 0;
 
spinlock_initialize(&instance->dev_lock, "cuda_dev");
 
/* Disable all interrupts from CUDA. */
pio_write_8(&dev->ier, IER_CLR | ALL_INT);
 
irq_initialize(&instance->irq);
instance->irq.devno = device_assign_devno();
instance->irq.inr = inr;
110,251 → 64,15
instance->irq.instance = instance;
instance->irq.cir = cir;
instance->irq.cir_arg = cir_arg;
instance->irq.preack = true;
}
return instance;
}
 
#include <print.h>
void cuda_wire(cuda_instance_t *instance, indev_t *kbrdin)
{
cuda_t *dev = instance->cuda;
 
ASSERT(instance);
ASSERT(kbrdin);
 
instance->kbrdin = kbrdin;
irq_register(&instance->irq);
 
/* Enable SR interrupt. */
pio_write_8(&dev->ier, TIP | TREQ);
pio_write_8(&dev->ier, IER_SET | SR_INT);
 
/* Enable ADB autopolling. */
cuda_autopoll_set(instance, true);
}
 
static irq_ownership_t cuda_claim(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t ifr;
 
spinlock_lock(&instance->dev_lock);
ifr = pio_read_8(&dev->ifr);
spinlock_unlock(&instance->dev_lock);
 
if ((ifr & SR_INT) == 0)
return IRQ_DECLINE;
 
return IRQ_ACCEPT;
}
 
static void cuda_irq_handler(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
uint8_t rbuf[CUDA_RCV_BUF_SIZE];
size_t len;
bool handle;
 
handle = false;
len = 0;
 
spinlock_lock(&instance->dev_lock);
 
/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
pio_write_8(&instance->cuda->ifr, SR_INT);
 
switch (instance->xstate) {
case cx_listen: cuda_irq_listen(irq); break;
case cx_receive: cuda_irq_receive(irq); break;
case cx_rcv_end: cuda_irq_rcv_end(irq, rbuf, &len);
handle = true; break;
case cx_send_start: cuda_irq_send_start(irq); break;
case cx_send: cuda_irq_send(irq); break;
}
 
spinlock_unlock(&instance->dev_lock);
 
/* Handle an incoming packet. */
if (handle)
cuda_packet_handle(instance, rbuf, len);
}
 
/** Interrupt in listen state.
*
* Start packet reception.
*/
static void cuda_irq_listen(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t b;
 
b = pio_read_8(&dev->b);
 
if ((b & TREQ) != 0) {
printf("cuda_irq_listen: no TREQ?!\n");
return;
}
 
pio_read_8(&dev->sr);
pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);
instance->xstate = cx_receive;
}
 
/** Interrupt in receive state.
*
* Receive next byte of packet.
*/
static void cuda_irq_receive(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t b, data;
 
data = pio_read_8(&dev->sr);
if (instance->bidx < CUDA_RCV_BUF_SIZE)
instance->rcv_buf[instance->bidx++] = data;
 
b = pio_read_8(&dev->b);
 
if ((b & TREQ) == 0) {
pio_write_8(&dev->b, b ^ TACK);
} else {
pio_write_8(&dev->b, b | TACK | TIP);
instance->xstate = cx_rcv_end;
}
}
 
/** Interrupt in rcv_end state.
*
* Terminate packet reception. Either go back to listen state or start
* receiving another packet if CUDA has one for us.
*/
static void cuda_irq_rcv_end(irq_t *irq, void *buf, size_t *len)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t data, b;
 
b = pio_read_8(&dev->b);
data = pio_read_8(&dev->sr);
 
if ((b & TREQ) == 0) {
instance->xstate = cx_receive;
pio_write_8(&dev->b, b & ~TIP);
} else {
instance->xstate = cx_listen;
cuda_send_start(instance);
}
 
memcpy(buf, instance->rcv_buf, instance->bidx);
*len = instance->bidx;
instance->bidx = 0;
}
 
/** Interrupt in send_start state.
*
* Process result of sending first byte (and send second on success).
*/
static void cuda_irq_send_start(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
uint8_t b;
 
b = pio_read_8(&dev->b);
 
if ((b & TREQ) == 0) {
/* Collision */
pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT);
pio_read_8(&dev->sr);
pio_write_8(&dev->b, pio_read_8(&dev->b) | TIP | TACK);
instance->xstate = cx_listen;
return;
}
 
pio_write_8(&dev->sr, instance->snd_buf[1]);
pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK);
instance->bidx = 2;
 
instance->xstate = cx_send;
}
 
/** Interrupt in send state.
*
* Send next byte or terminate transmission.
*/
static void cuda_irq_send(irq_t *irq)
{
cuda_instance_t *instance = irq->instance;
cuda_t *dev = instance->cuda;
 
if (instance->bidx < instance->snd_bytes) {
/* Send next byte. */
pio_write_8(&dev->sr, instance->snd_buf[instance->bidx++]);
pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK);
return;
}
 
/* End transfer. */
instance->snd_bytes = 0;
instance->bidx = 0;
 
pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT);
pio_read_8(&dev->sr);
pio_write_8(&dev->b, pio_read_8(&dev->b) | TACK | TIP);
 
instance->xstate = cx_listen;
/* TODO: Match reply with request. */
}
 
static void cuda_packet_handle(cuda_instance_t *instance, uint8_t *data, size_t len)
{
if (data[0] != 0x00 || data[1] != 0x40 || (data[2] != 0x2c
&& data[2] != 0x8c))
return;
 
/* The packet contains one or two scancodes. */
if (data[3] != 0xff)
indev_push_character(instance->kbrdin, data[3]);
if (data[4] != 0xff)
indev_push_character(instance->kbrdin, data[4]);
}
 
static void cuda_autopoll_set(cuda_instance_t *instance, bool enable)
{
instance->snd_buf[0] = PT_CUDA;
instance->snd_buf[1] = CPT_AUTOPOLL;
instance->snd_buf[2] = enable ? 0x01 : 0x00;
instance->snd_bytes = 3;
instance->bidx = 0;
 
cuda_send_start(instance);
}
 
static void cuda_send_start(cuda_instance_t *instance)
{
cuda_t *dev = instance->cuda;
 
ASSERT(instance->xstate == cx_listen);
 
if (instance->snd_bytes == 0)
return;
 
/* Check for incoming data. */
if ((pio_read_8(&dev->b) & TREQ) == 0)
return;
 
pio_write_8(&dev->acr, pio_read_8(&dev->acr) | SR_OUT);
pio_write_8(&dev->sr, instance->snd_buf[0]);
pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);
 
instance->xstate = cx_send_start;
}
 
 
/** @}
*/
/branches/dynload/kernel/genarch/src/mm/asid.c
65,7 → 65,7
#include <adt/list.h>
#include <debug.h>
 
static size_t asids_allocated = 0;
static count_t asids_allocated = 0;
 
/** Allocate free address space identifier.
*
120,7 → 120,7
* of TLB entries (e.g. TSB on sparc64), the
* cache must be invalidated as well.
*/
as_invalidate_translation_cache(as, 0, (size_t) -1);
as_invalidate_translation_cache(as, 0, (count_t) -1);
/*
* Get the system rid of the stolen ASID.
/branches/dynload/kernel/genarch/src/mm/page_ht.c
51,8 → 51,8
#include <adt/hash_table.h>
#include <align.h>
 
static size_t hash(unative_t key[]);
static bool compare(unative_t key[], size_t keys, link_t *item);
static index_t hash(unative_t key[]);
static bool compare(unative_t key[], count_t keys, link_t *item);
static void remove_callback(link_t *item);
 
static void ht_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame,
93,11 → 93,11
*
* @return Index into page hash table.
*/
size_t hash(unative_t key[])
index_t hash(unative_t key[])
{
as_t *as = (as_t *) key[KEY_AS];
uintptr_t page = (uintptr_t) key[KEY_PAGE];
size_t index;
index_t index;
/*
* Virtual page addresses have roughly the same probability
124,7 → 124,7
*
* @return true on match, false otherwise.
*/
bool compare(unative_t key[], size_t keys, link_t *item)
bool compare(unative_t key[], count_t keys, link_t *item)
{
pte_t *t;
 
192,8 → 192,6
t->k = !(flags & PAGE_USER);
t->c = (flags & PAGE_CACHEABLE) != 0;
t->p = !(flags & PAGE_NOT_PRESENT);
t->a = false;
t->d = false;
 
t->as = as;
t->page = ALIGN_DOWN(page, PAGE_SIZE);
/branches/dynload/kernel/genarch/src/acpi/acpi.c
167,13 → 167,10
LOG("%p: ACPI Root System Description Pointer\n", acpi_rsdp);
 
acpi_rsdt = (struct acpi_rsdt *) (unative_t) acpi_rsdp->rsdt_address;
if (acpi_rsdp->revision)
acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address);
if (acpi_rsdp->revision) acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address);
 
if (acpi_rsdt)
map_sdt((struct acpi_sdt_header *) acpi_rsdt);
if (acpi_xsdt)
map_sdt((struct acpi_sdt_header *) acpi_xsdt);
if (acpi_rsdt) map_sdt((struct acpi_sdt_header *) acpi_rsdt);
if (acpi_xsdt) map_sdt((struct acpi_sdt_header *) acpi_xsdt);
 
if (acpi_rsdt && !acpi_sdt_check((uint8_t *) acpi_rsdt)) {
printf("RSDT: bad checksum\n");
184,10 → 181,8
return;
}
 
if (acpi_xsdt)
configure_via_xsdt();
else if (acpi_rsdt)
configure_via_rsdt();
if (acpi_xsdt) configure_via_xsdt();
else if (acpi_rsdt) configure_via_rsdt();
 
}
 
/branches/dynload/kernel/genarch/src/acpi/madt.c
62,11 → 62,11
struct madt_l_apic *madt_l_apic_entries = NULL;
struct madt_io_apic *madt_io_apic_entries = NULL;
 
size_t madt_l_apic_entry_index = 0;
size_t madt_io_apic_entry_index = 0;
size_t madt_l_apic_entry_cnt = 0;
size_t madt_io_apic_entry_cnt = 0;
size_t cpu_count = 0;
index_t madt_l_apic_entry_index = 0;
index_t madt_io_apic_entry_index = 0;
count_t madt_l_apic_entry_cnt = 0;
count_t madt_io_apic_entry_cnt = 0;
count_t cpu_count = 0;
 
struct madt_apic_header * * madt_entries_index = NULL;
unsigned int madt_entries_index_cnt = 0;
86,10 → 86,10
/*
* ACPI MADT Implementation of SMP configuration interface.
*/
static size_t madt_cpu_count(void);
static bool madt_cpu_enabled(size_t i);
static bool madt_cpu_bootstrap(size_t i);
static uint8_t madt_cpu_apic_id(size_t i);
static count_t madt_cpu_count(void);
static bool madt_cpu_enabled(index_t i);
static bool madt_cpu_bootstrap(index_t i);
static uint8_t madt_cpu_apic_id(index_t i);
static int madt_irq_to_pin(unsigned int irq);
 
struct smp_config_operations madt_config_operations = {
100,12 → 100,12
.irq_to_pin = madt_irq_to_pin
};
 
size_t madt_cpu_count(void)
count_t madt_cpu_count(void)
{
return madt_l_apic_entry_cnt;
}
 
bool madt_cpu_enabled(size_t i)
bool madt_cpu_enabled(index_t i)
{
ASSERT(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
112,13 → 112,13
 
}
 
bool madt_cpu_bootstrap(size_t i)
bool madt_cpu_bootstrap(index_t i)
{
ASSERT(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
}
 
uint8_t madt_cpu_apic_id(size_t i)
uint8_t madt_cpu_apic_id(index_t i)
{
ASSERT(i < madt_l_apic_entry_cnt);
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
/branches/dynload/kernel/Makefile
44,12 → 44,12
## Common compiler flags
#
 
DEFS = -DKERNEL -DRELEASE=$(RELEASE) "-DNAME=$(NAME)" -D__$(BITS)_BITS__ -D__$(ENDIANESS)__
DEFS = -DKERNEL -DRELEASE=$(RELEASE) "-DNAME=$(NAME)"
 
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../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 -nostdlib -nostdinc -pipe
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \
-nostdlib -nostdinc -pipe
 
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \
-fno-builtin -Wall -Wmissing-prototypes -Werror \
/branches/dynload/kernel/doc/mm
5,10 → 5,10
 
1.1 Hierarchical 4-level per address space page tables
 
SPARTAN kernel deploys generic interface for 4-level page tables for these
architectures: amd64, arm32, ia32, mips32 and ppc32. In this setting, page
tables are hierarchical and are not shared by address spaces (i.e. one set of
page tables per address space).
SPARTAN kernel deploys generic interface for 4-level page tables
for these architectures: amd64, ia32, mips32 and ppc32. In this
setting, page tables are hierarchical and are not shared by
address spaces (i.e. one set of page tables per address space).
 
 
VADDR
/branches/dynload/uspace/app/getvc/version.h
File deleted
/branches/dynload/uspace/app/getvc/Makefile
File deleted
/branches/dynload/uspace/app/getvc/getvc.h
File deleted
/branches/dynload/uspace/app/getvc/version.c
File deleted
/branches/dynload/uspace/app/getvc/getvc.c
File deleted
/branches/dynload/uspace/app/bdsh/cmds/modules/bdd/entry.h
File deleted
/branches/dynload/uspace/app/bdsh/cmds/modules/bdd/bdd.c
File deleted
/branches/dynload/uspace/app/bdsh/cmds/modules/bdd/bdd_def.h
File deleted
/branches/dynload/uspace/app/bdsh/cmds/modules/bdd/bdd.h
File deleted
/branches/dynload/uspace/app/bdsh/cmds/modules/modules.h
20,7 → 20,6
#include "help/entry.h"
#include "mkdir/entry.h"
#include "rm/entry.h"
#include "bdd/entry.h"
#include "cat/entry.h"
#include "touch/entry.h"
#include "ls/entry.h"
39,7 → 38,6
#include "help/help_def.h"
#include "mkdir/mkdir_def.h"
#include "rm/rm_def.h"
#include "bdd/bdd_def.h"
#include "cat/cat_def.h"
#include "touch/touch_def.h"
#include "ls/ls_def.h"
/branches/dynload/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
37,7 → 37,6
#include <sys/stat.h>
#include <getopt.h>
#include <stdarg.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
/branches/dynload/uspace/app/bdsh/cmds/modules/ls/ls.c
50,9 → 50,48
 
static char *cmdname = "ls";
 
static inline off_t flen(const char *f)
{
int fd;
off_t size;
 
fd = open(f, O_RDONLY);
if (fd == -1)
return 0;
 
size = lseek(fd, 0, SEEK_END);
close(fd);
 
if (size < 0)
size = 0;
 
return size;
}
 
static unsigned int ls_scope(const char *path)
{
int fd;
DIR *dirp;
 
dirp = opendir(path);
if (dirp) {
closedir(dirp);
return LS_DIR;
}
 
fd = open(path, O_RDONLY);
if (fd > 0) {
close(fd);
return LS_FILE;
}
 
return LS_BOGUS;
}
 
static void ls_scan_dir(const char *d, DIR *dirp)
{
struct dirent *dp;
unsigned int scope;
char *buff;
 
if (! dirp)
69,7 → 108,20
/* Don't worry if inserting a double slash, this will be fixed by
* absolutize() later with subsequent calls to open() or readdir() */
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
ls_print(dp->d_name, buff);
scope = ls_scope(buff);
switch (scope) {
case LS_DIR:
ls_print_dir(dp->d_name);
break;
case LS_FILE:
ls_print_file(dp->d_name, buff);
break;
case LS_BOGUS:
/* Odd chance it was deleted from the time readdir() found
* it and the time that it was scoped */
printf("ls: skipping bogus node %s\n", dp->d_name);
break;
}
}
 
free(buff);
77,7 → 129,7
return;
}
 
/* ls_print currently does nothing more than print the entry.
/* ls_print_* currently does nothing more than print the entry.
* in the future, we will likely pass the absolute path, and
* some sort of ls_options structure that controls how each
* entry is printed and what is printed about it.
84,24 → 136,17
*
* Now we just print basic DOS style lists */
 
static void ls_print(const char *name, const char *pathname)
static void ls_print_dir(const char *d)
{
struct stat s;
int rc;
printf("%-40s\t<dir>\n", d);
 
rc = stat(pathname, &s);
if (rc != 0) {
/* Odd chance it was deleted from the time readdir() found it */
printf("ls: skipping bogus node %s\n", pathname);
printf("rc=%d\n", rc);
return;
}
if (s.is_file)
printf("%-40s\t%llu\n", name, (long long) s.size);
else
printf("%-40s\n", name);
return;
}
 
static void ls_print_file(const char *name, const char *pathname)
{
printf("%-40s\t%llu\n", name, (long long) flen(pathname));
 
return;
}
 
121,7 → 166,7
int cmd_ls(char **argv)
{
unsigned int argc;
struct stat s;
unsigned int scope;
char *buff;
DIR *dirp;
 
139,17 → 184,19
else
str_cpy(buff, PATH_MAX, argv[1]);
 
if (stat(buff, &s)) {
scope = ls_scope(buff);
 
switch (scope) {
case LS_BOGUS:
cli_error(CL_ENOENT, buff);
free(buff);
return CMD_FAILURE;
}
 
if (s.is_file) {
ls_print(buff, buff);
} else {
case LS_FILE:
ls_print_file(buff, buff);
break;
case LS_DIR:
dirp = opendir(buff);
if (!dirp) {
if (! dirp) {
/* May have been deleted between scoping it and opening it */
cli_error(CL_EFAIL, "Could not stat %s", buff);
free(buff);
157,6 → 204,7
}
ls_scan_dir(buff, dirp);
closedir(dirp);
break;
}
 
free(buff);
/branches/dynload/uspace/app/bdsh/cmds/modules/ls/ls.h
6,8 → 6,11
#define LS_FILE 1
#define LS_DIR 2
 
 
static unsigned int ls_scope(const char *);
static void ls_scan_dir(const char *, DIR *);
static void ls_print(const char *, const char *);
static void ls_print_dir(const char *);
static void ls_print_file(const char *, const char *);
 
#endif /* LS_H */
 
/branches/dynload/uspace/app/bdsh/cmds/modules/rm/rm.c
34,8 → 34,6
#include <fcntl.h>
#include <dirent.h>
#include <getopt.h>
#include <mem.h>
#include <string.h>
 
#include "config.h"
#include "errors.h"
209,7 → 207,7
}
}
 
if ((unsigned) optind == argc) {
if (optind == argc) {
cli_error(CL_EFAIL,
"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
rm_end(&rm);
/branches/dynload/uspace/app/bdsh/cmds/modules/kcon/kcon.c
30,8 → 30,7
 
#include <stdio.h>
#include <stdlib.h>
#include <io/console.h>
#include <vfs/vfs.h>
#include <console.h>
#include "config.h"
#include "util.h"
#include "errors.h"
66,7 → 65,7
return CMD_FAILURE;
}
 
console_kcon_enable(fphone(stdout));
console_kcon_enable();
 
return CMD_SUCCESS;
}
/branches/dynload/uspace/app/bdsh/cmds/modules/cp/cp.c
172,8 → 172,7
 
int cmd_cp(char **argv)
{
unsigned int argc, verbose = 0;
int buffer = 0;
unsigned int argc, buffer = 0, verbose = 0;
int c, opt_ind;
int64_t ret;
 
/branches/dynload/uspace/app/bdsh/cmds/modules/pwd/pwd.c
30,7 → 30,6
 
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
 
#include "config.h"
#include "errors.h"
/branches/dynload/uspace/app/bdsh/Makefile
33,14 → 33,12
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
LIBBLOCK_PREFIX = ../../lib/libblock
 
include $(LIBC_PREFIX)/Makefile.toolchain
include $(LIBC_PREFIX)/Makefile.app
 
CFLAGS += -I../../srv/kbd/include -I$(LIBBLOCK_PREFIX)
CFLAGS += -I../../srv/kbd/include
 
LIBS += $(LIBBLOCK_PREFIX)/libblock.a $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=$(RELEASE)
 
PROGRAM = bdsh
53,7 → 51,6
cmds/modules/help/ \
cmds/modules/mkdir/ \
cmds/modules/rm/ \
cmds/modules/bdd/ \
cmds/modules/cat/ \
cmds/modules/touch/ \
cmds/modules/ls/ \
71,7 → 68,6
cmds/modules/help/help.c \
cmds/modules/mkdir/mkdir.c \
cmds/modules/rm/rm.c \
cmds/modules/bdd/bdd.c \
cmds/modules/cat/cat.c \
cmds/modules/touch/touch.c \
cmds/modules/ls/ls.c \
/branches/dynload/uspace/app/bdsh/input.c
32,10 → 32,10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/console.h>
#include <io/keycode.h>
#include <io/style.h>
#include <vfs/vfs.h>
#include <io/stream.h>
#include <console.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <errno.h>
#include <bool.h>
 
100,7 → 100,7
 
static void read_line(char *buffer, int n)
{
console_event_t ev;
kbd_event_t ev;
size_t offs, otmp;
wchar_t dec;
 
107,12 → 107,11
offs = 0;
while (true) {
fflush(stdout);
if (!console_get_event(fphone(stdin), &ev))
if (kbd_get_event(&ev) < 0)
return;
if (ev.type != KEY_PRESS)
if (ev.type == KE_RELEASE)
continue;
 
if (ev.key == KC_ENTER || ev.key == KC_NENTER)
break;
if (ev.key == KC_BACKSPACE) {
132,8 → 131,9
continue;
}
if (ev.c >= ' ') {
//putchar(ev.c);
if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK)
putchar(ev.c);
console_putchar(ev.c);
}
}
putchar('\n');
147,11 → 147,9
{
char line[INPUT_MAX];
 
fflush(stdout);
console_set_style(fphone(stdout), STYLE_EMPHASIS);
console_set_style(STYLE_EMPHASIS);
printf("%s", usr->prompt);
fflush(stdout);
console_set_style(fphone(stdout), STYLE_NORMAL);
console_set_style(STYLE_NORMAL);
 
read_line(line, INPUT_MAX);
/* Make sure we don't have rubbish or a C/R happy user */
/branches/dynload/uspace/app/bdsh/exec.c
112,9 → 112,7
unsigned int try_exec(char *cmd, char **argv)
{
task_id_t tid;
task_exit_t texit;
char *tmp;
int retval;
 
tmp = str_dup(find_command(cmd));
free(found);
125,14 → 123,7
if (tid == 0) {
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd);
return 1;
} else {
return 0;
}
task_wait(tid, &texit, &retval);
if (texit != TASK_EXIT_NORMAL) {
printf("Command failed (unexpectedly terminated).\n");
} else if (retval != 0) {
printf("Command failed (return value %d).\n", retval);
}
 
return 0;
}
/branches/dynload/uspace/app/bdsh/util.c
53,6 → 53,14
* string */
unsigned int cli_set_prompt(cliuser_t *usr)
{
usr->prompt = (char *) realloc(usr->prompt, PATH_MAX);
if (NULL == usr->prompt) {
cli_error(CL_ENOMEM, "Can not allocate prompt");
cli_errno = CL_ENOMEM;
return 1;
}
memset(usr->prompt, 0, sizeof(usr->prompt));
 
usr->cwd = (char *) realloc(usr->cwd, PATH_MAX);
if (NULL == usr->cwd) {
cli_error(CL_ENOMEM, "Can not allocate cwd");
59,11 → 67,13
cli_errno = CL_ENOMEM;
return 1;
}
if (!getcwd(usr->cwd, PATH_MAX))
memset(usr->cwd, 0, sizeof(usr->cwd));
 
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1);
 
if (NULL == usr->cwd)
snprintf(usr->cwd, PATH_MAX, "(unknown)");
 
if (usr->prompt)
free(usr->prompt);
asprintf(&usr->prompt, "%s # ", usr->cwd);
 
return 0;
/branches/dynload/uspace/app/tester/mm/malloc1.def
File deleted
/branches/dynload/uspace/app/tester/mm/malloc1.c
File deleted
/branches/dynload/uspace/app/tester/tester.c
27,10 → 27,10
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup tester User space tester
* @brief User space testing infrastructure.
/** @addtogroup tester User space Tester
* @brief User space testing infrastructure.
* @{
*/
*/
/**
* @file
*/
37,44 → 37,48
 
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "tester.h"
 
bool test_quiet;
int test_argc;
char **test_argv;
int myservice = 0;
int phones[MAX_PHONES];
int connections[MAX_CONNECTIONS];
ipc_callid_t callids[MAX_CONNECTIONS];
 
test_t tests[] = {
#include "thread/thread1.def"
#include "print/print1.def"
#include "print/print2.def"
#include "print/print3.def"
#include "print/print4.def"
#include "console/console1.def"
#include "stdio/stdio1.def"
#include "stdio/stdio2.def"
#include "fault/fault1.def"
#include "fault/fault2.def"
#include "vfs/vfs1.def"
#include "ipc/ping_pong.def"
#include "ipc/register.def"
#include "ipc/connect.def"
#include "ipc/send_async.def"
#include "ipc/send_sync.def"
#include "ipc/answer.def"
#include "ipc/hangup.def"
#include "ipc/ping_pong.def"
#include "devmap/devmap1.def"
#include "loop/loop1.def"
#include "mm/malloc1.def"
{NULL, NULL, NULL, false}
#include "vfs/vfs1.def"
#include "console/console1.def"
#include "stdio/stdio1.def"
#include "stdio/stdio2.def"
{NULL, NULL, NULL}
};
 
static bool run_test(test_t *test)
{
printf("%s\t\t%s\n", test->name, test->desc);
/* Execute the test */
char *ret = test->entry();
char * ret = test->entry(false);
if (ret == NULL) {
printf("\nTest passed\n");
printf("Test passed\n\n");
return true;
}
printf("\n%s\n", ret);
 
printf("%s\n\n", ret);
return false;
}
 
83,12 → 87,11
test_t *test;
unsigned int i = 0;
unsigned int n = 0;
 
printf("\n*** Running all safe tests ***\n\n");
 
for (test = tests; test->name != NULL; test++) {
if (test->safe) {
printf("%s (%s)\n", test->name, test->desc);
if (run_test(test))
i++;
else
95,52 → 98,63
n++;
}
}
printf("\nCompleted, %u tests run, %u passed.\n", i + n, i);
 
printf("\nSafe tests completed, %u tests run, %u passed.\n\n", i + n, i);
}
 
static void list_tests(void)
{
size_t len = 0;
test_t *test;
for (test = tests; test->name != NULL; test++) {
if (str_length(test->name) > len)
len = str_length(test->name);
}
char c = 'a';
for (test = tests; test->name != NULL; test++)
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)"));
for (test = tests; test->name != NULL; test++, c++)
printf("%c\t%s\t\t%s%s\n", c, test->name, test->desc, (test->safe ? "" : " (unsafe)"));
printf("%-*s Run all safe tests\n", len, "*");
printf("*\t\t\tRun all safe tests\n");
}
 
int main(int argc, char *argv[])
int main(int argc, char **argv)
{
if (argc < 2) {
printf("Usage:\n\n");
printf("%s <test> [args ...]\n\n", argv[0]);
printf("Number of arguments: %d\n", argc);
if (argv) {
printf("Arguments:");
while (*argv) {
printf(" '%s'", *argv++);
}
printf("\n");
}
 
while (1) {
char c;
test_t *test;
list_tests();
return 0;
}
test_quiet = false;
test_argc = argc - 2;
test_argv = argv + 2;
if (str_cmp(argv[1], "*") == 0) {
run_safe_tests();
return 0;
}
test_t *test;
for (test = tests; test->name != NULL; test++) {
if (str_cmp(argv[1], test->name) == 0) {
return (run_test(test) ? 0 : -1);
printf("> ");
c = getchar();
printf("%c\n", c);
if ((c >= 'a') && (c <= 'z')) {
for (test = tests; test->name != NULL; test++, c--)
if (c == 'a')
break;
if (test->name == NULL)
printf("Unknown test\n\n");
else
run_test(test);
} else if (c == '*') {
run_safe_tests();
} else if (c < 0) {
/* got EOF */
break;
} else {
printf("Invalid test\n\n");
}
}
printf("Unknown test \"%s\"\n", argv[1]);
return -2;
 
return 0;
}
 
/** @}
/branches/dynload/uspace/app/tester/ipc/ping_pong.c
28,51 → 28,41
 
#include <stdio.h>
#include <stdlib.h>
#include <console.h>
#include <sys/time.h>
#include <ipc/ns.h>
#include <async.h>
#include <errno.h>
#include "../tester.h"
 
#define DURATION_SECS 10
#define COUNT_GRANULARITY 100
#define DURATION_SECS 10
#define COUNT_GRANULARITY 100
 
char *test_ping_pong(void)
char * test_ping_pong(bool quiet)
{
TPRINTF("Pinging ns server for %d seconds...", DURATION_SECS);
struct timeval start;
if (gettimeofday(&start, NULL) != 0) {
TPRINTF("\n");
return "Failed getting the time";
}
uint64_t count = 0;
int i;
int w, h;
struct timeval start, now;
long count;
 
printf("Pinging console server for %d seconds...\n", DURATION_SECS);
 
if (gettimeofday(&start, NULL) != 0)
return "Failed getting the time.";
 
count = 0;
 
while (true) {
struct timeval now;
if (gettimeofday(&now, NULL) != 0) {
TPRINTF("\n");
return "Failed getting the time";
}
if (gettimeofday(&now, NULL) != 0)
return "Failed getting the time.";
 
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
break;
size_t i;
for (i = 0; i < COUNT_GRANULARITY; i++) {
int retval = async_req_0_0(PHONE_NS, NS_PING);
if (retval != EOK) {
TPRINTF("\n");
return "Failed to send ping message";
}
}
 
for (i = 0; i < COUNT_GRANULARITY; i++)
console_get_size(&w, &h);
count += COUNT_GRANULARITY;
}
TPRINTF("OK\nCompleted %llu round trips in %u seconds, %llu rt/s.\n",
count, DURATION_SECS, count / DURATION_SECS);
 
printf("Completed %ld round trips in %d seconds, %ld RT/s.\n", count,
DURATION_SECS, count / DURATION_SECS);
 
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/send_sync.c
0,0 → 1,53
/*
* Copyright (c) 2006 Ondrej Palkovsky
* 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 <stdio.h>
#include <unistd.h>
#include "../tester.h"
#include <ipc/ipc.h>
 
char * test_send_sync(bool quiet)
{
int phoneid;
int res;
char c;
 
printf("Select phoneid to send msg: 2-9 (q to skip)\n");
do {
c = getchar();
if ((c == 'Q') || (c == 'q'))
return TEST_SKIPPED;
} while (c < '2' || c > '9');
phoneid = c - '0';
printf("Sending msg...");
res = ipc_call_sync_0_0(phoneid, 2000);
printf("done: %d\n", res);
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/hangup.c
0,0 → 1,53
/*
* Copyright (c) 2006 Ondrej Palkovsky
* 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 <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "../tester.h"
 
char * test_hangup(bool quiet)
{
char c;
int res;
int phoneid;
 
printf("Select phoneid to hangup: 2-9 (q to skip)\n");
do {
c = getchar();
if ((c == 'Q') || (c == 'q'))
return TEST_SKIPPED;
} while (c < '2' || c > '9');
phoneid = c - '0';
printf("Hanging up...");
res = ipc_hangup(phoneid);
printf("done: %d\n", phoneid);
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/send_async.c
0,0 → 1,57
/*
* Copyright (c) 2006 Ondrej Palkovsky
* 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 <stdio.h>
#include <unistd.h>
#include "../tester.h"
 
static void callback(void *_private, int retval, ipc_call_t *data)
{
printf("Received response to msg %d - retval: %d.\n", _private, retval);
}
 
char * test_send_async(bool quiet)
{
int phoneid;
static int msgid = 1;
char c;
 
printf("Select phoneid to send msg: 2-9 (q to skip)\n");
do {
c = getchar();
if ((c == 'Q') || (c == 'q'))
return TEST_SKIPPED;
} while (c < '2' || c > '9');
phoneid = c - '0';
 
ipc_call_async_0(phoneid, 2000, (void *) msgid, callback, 1);
printf("Async sent - msg %d\n", msgid);
msgid++;
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/connect.c
28,46 → 28,32
 
#include <stdio.h>
#include <unistd.h>
#include <atomic.h>
#include "../tester.h"
 
static atomic_t finish;
 
static void callback(void *priv, int retval, ipc_call_t *data)
char * test_connect(bool quiet)
{
atomic_set(&finish, 1);
}
char c;
int svc;
int phid;
 
char *test_connect(void)
{
TPRINTF("Connecting to %u...", IPC_TEST_SERVICE);
int phone = ipc_connect_me_to(PHONE_NS, IPC_TEST_SERVICE, 0, 0);
if (phone > 0) {
TPRINTF("phoneid %d\n", phone);
} else {
TPRINTF("\n");
return "ipc_connect_me_to() failed";
}
printf("Choose one service: 0:10000....9:10009 (q to skip)\n");
do {
c = getchar();
if ((c == 'Q') || (c == 'q'))
return TEST_SKIPPED;
} while (c < '0' || c > '9');
printf("Sending synchronous message...\n");
int retval = ipc_call_sync_0_0(phone, IPC_TEST_METHOD);
TPRINTF("Received response to synchronous message\n");
svc = IPC_TEST_START + c - '0';
if (svc == myservice)
return "Currently cannot connect to myself, update test";
TPRINTF("Sending asynchronous message...\n");
atomic_set(&finish, 0);
ipc_call_async_0(phone, IPC_TEST_METHOD, NULL, callback, 1);
while (atomic_get(&finish) != 1)
TPRINTF(".");
TPRINTF("Received response to asynchronous message\n");
printf("Connecting to %d..", svc);
phid = ipc_connect_me_to(PHONE_NS, svc, 0, 0);
if (phid > 0) {
printf("phoneid: %d\n", phid);
phones[phid] = 1;
} else
return "Error";
TPRINTF("Hanging up...");
retval = ipc_hangup(phone);
if (retval == 0) {
TPRINTF("OK\n");
} else {
TPRINTF("\n");
return "ipc_hangup() failed";
}
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/register.c
32,58 → 32,58
#include <errno.h>
#include "../tester.h"
 
#define MAX_CONNECTIONS 50
 
static int connections[MAX_CONNECTIONS];
 
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
unsigned int i;
TPRINTF("Connected phone %#x accepting\n", icall->in_phone_hash);
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t phonehash = icall->in_phone_hash;
int retval;
int i;
 
printf("Connected phone: %P, accepting\n", icall->in_phone_hash);
ipc_answer_0(iid, EOK);
for (i = 0; i < MAX_CONNECTIONS; i++) {
for (i = 0; i < 1024; i++)
if (!connections[i]) {
connections[i] = icall->in_phone_hash;
connections[i] = phonehash;
break;
}
}
while (true) {
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
int retval;
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
TPRINTF("Phone %#x hung up\n", icall->in_phone_hash);
printf("Phone (%P) hung up.\n", phonehash);
retval = 0;
break;
case IPC_TEST_METHOD:
TPRINTF("Received well known message from %#x: %#x\n",
icall->in_phone_hash, callid);
ipc_answer_0(callid, EOK);
break;
default:
TPRINTF("Received unknown message from %#x: %#x\n",
icall->in_phone_hash, callid);
ipc_answer_0(callid, ENOENT);
break;
printf("Received message from %P: %X\n", phonehash,
callid);
for (i = 0; i < 1024; i++)
if (!callids[i]) {
callids[i] = callid;
break;
}
continue;
}
ipc_answer_0(callid, retval);
}
}
 
char *test_register(void)
char * test_register(bool quiet)
{
int i;
async_set_client_connection(client_connection);
 
for (i = IPC_TEST_START; i < IPC_TEST_START + 10; i++) {
ipcarg_t phonead;
int res = ipc_connect_to_me(PHONE_NS, i, 0, 0, &phonead);
if (!res)
break;
printf("Failed registering as %d..:%d\n", i, res);
}
printf("Registered as service: %d\n", i);
myservice = i;
ipcarg_t phonead;
int res = ipc_connect_to_me(PHONE_NS, IPC_TEST_SERVICE, 0, 0, &phonead);
if (res != 0)
return "Failed registering IPC service";
TPRINTF("Registered as service %u, accepting connections\n", IPC_TEST_SERVICE);
async_manager();
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/answer.c
0,0 → 1,76
/*
* Copyright (c) 2006 Ondrej Palkovsky
* 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 <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "../tester.h"
 
char * test_answer(bool quiet)
{
int i,cnt, errn = 0;
char c;
 
cnt = 0;
for (i = 0;i < 50; i++) {
if (callids[i]) {
printf("%d: %P\n", cnt, callids[i]);
cnt++;
}
if (cnt >= 10)
break;
}
if (!cnt)
return NULL;
printf("Choose message:\n");
do {
c = getchar();
} while (c < '0' || (c-'0') >= cnt);
cnt = c - '0' + 1;
for (i = 0; cnt; i++)
if (callids[i])
cnt--;
i -= 1;
 
printf("Normal (n) or hangup (h) or error(e) message?\n");
do {
c = getchar();
} while (c != 'n' && c != 'h' && c != 'e');
if (c == 'n')
errn = 0;
else if (c == 'h')
errn = EHANGUP;
else if (c == 'e')
errn = ENOENT;
printf("Answering %P\n", callids[i]);
ipc_answer_0(callids[i], errn);
callids[i] = 0;
return NULL;
}
/branches/dynload/uspace/app/tester/ipc/hangup.def
0,0 → 1,6
{
"hangup",
"IPC hangup test",
&test_hangup,
true
},
/branches/dynload/uspace/app/tester/ipc/send_sync.def
0,0 → 1,6
{
"send_sync",
"IPC send sync message test",
&test_send_sync,
true
},
/branches/dynload/uspace/app/tester/ipc/send_async.def
0,0 → 1,6
{
"send_async",
"IPC send async message test",
&test_send_async,
true
},
/branches/dynload/uspace/app/tester/ipc/answer.def
0,0 → 1,6
{
"answer",
"IPC answer message test",
&test_answer,
true
},
/branches/dynload/uspace/app/tester/tester.h
39,45 → 39,43
#include <bool.h>
#include <ipc/ipc.h>
 
#define IPC_TEST_SERVICE 10240
#define IPC_TEST_METHOD 2000
#define IPC_TEST_START 10000
#define MAX_PHONES 20
#define MAX_CONNECTIONS 50
#define TEST_SKIPPED "Test Skipped"
 
extern bool test_quiet;
extern int test_argc;
extern char **test_argv;
extern int myservice;
extern int phones[MAX_PHONES];
extern int connections[MAX_CONNECTIONS];
extern ipc_callid_t callids[MAX_CONNECTIONS];
 
#define TPRINTF(format, ...) \
{ \
if (!test_quiet) { \
fprintf(stderr, format, ##__VA_ARGS__); \
} \
}
typedef char * (* test_entry_t)(bool);
 
typedef char *(*test_entry_t)(void);
 
typedef struct {
char *name;
char *desc;
char * name;
char * desc;
test_entry_t entry;
bool safe;
} test_t;
 
extern char *test_thread1(void);
extern char *test_print1(void);
extern char *test_print2(void);
extern char *test_print3(void);
extern char *test_print4(void);
extern char *test_console1(void);
extern char *test_stdio1(void);
extern char *test_stdio2(void);
extern char *test_fault1(void);
extern char *test_fault2(void);
extern char *test_vfs1(void);
extern char *test_ping_pong(void);
extern char *test_register(void);
extern char *test_connect(void);
extern char *test_loop1(void);
extern char *test_malloc1(void);
extern char * test_thread1(bool quiet);
extern char * test_print1(bool quiet);
extern char * test_print4(bool quiet);
extern char * test_fault1(bool quiet);
extern char * test_fault2(bool quiet);
extern char * test_register(bool quiet);
extern char * test_connect(bool quiet);
extern char * test_send_async(bool quiet);
extern char * test_send_sync(bool quiet);
extern char * test_answer(bool quiet);
extern char * test_hangup(bool quiet);
extern char * test_ping_pong(bool quiet);
extern char * test_devmap1(bool quiet);
extern char * test_loop1(bool quiet);
extern char * test_vfs1(bool quiet);
extern char * test_console1(bool quiet);
extern char * test_stdio1(bool quiet);
extern char * test_stdio2(bool quiet);
 
extern test_t tests[];
 
/branches/dynload/uspace/app/tester/Makefile
44,20 → 44,22
SOURCES = tester.c \
thread/thread1.c \
print/print1.c \
print/print2.c \
print/print3.c \
print/print4.c \
console/console1.c \
stdio/stdio1.c \
stdio/stdio2.c \
fault/fault1.c \
fault/fault2.c \
vfs/vfs1.c \
ipc/ping_pong.c \
ipc/register.c \
ipc/connect.c \
ipc/send_async.c \
ipc/send_sync.c \
ipc/answer.c \
ipc/hangup.c \
ipc/ping_pong.c \
loop/loop1.c \
mm/malloc1.c
devmap/devmap1.c \
console/console1.c \
stdio/stdio1.c \
stdio/stdio2.c \
vfs/vfs1.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
79,7 → 81,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/app/tester/devmap/devmap1.c
0,0 → 1,322
/*
* Copyright (c) 2007 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <unistd.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <async.h>
#include <errno.h>
#include <ipc/devmap.h>
#include "../tester.h"
 
#include <time.h>
 
#define TEST_DEVICE1 "TestDevice1"
#define TEST_DEVICE2 "TestDevice2"
 
/** Handle requests from clients
*
*/
static void driver_client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
printf("connected: method=%u arg1=%u, arg2=%u arg3=%u.\n",
IPC_GET_METHOD(*icall), IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall),
IPC_GET_ARG3(*icall));
 
printf("driver_client_connection.\n");
ipc_answer_0(iid, EOK);
 
/* Ignore parameters, the connection is already opened */
while (1) {
callid = async_get_call(&call);
retval = EOK;
printf("method=%u arg1=%u, arg2=%u arg3=%u.\n",
IPC_GET_METHOD(call), IPC_GET_ARG1(call),
IPC_GET_ARG2(call), IPC_GET_ARG3(call));
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/* TODO: Handle hangup */
return;
default:
printf("Unknown device method %u.\n",
IPC_GET_METHOD(call));
retval = ENOENT;
}
ipc_answer_0(callid, retval);
}
return;
}
 
static int device_client_fibril(void *arg)
{
int handle;
int device_phone;
 
handle = (int)arg;
 
device_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, handle);
 
if (device_phone < 0) {
printf("Failed to connect to devmap as client (handle = %u).\n",
handle);
return -1;
}
/*
* device_phone = (int) IPC_GET_ARG5(answer);
*/
printf("Connected to device.\n");
ipc_call_sync_1_0(device_phone, 1024, 1025);
/*
* ipc_hangup(device_phone);
*/
ipc_hangup(device_phone);
 
return EOK;
}
 
/** Communication test with device.
* @param handle handle to tested instance.
*/
static int device_client(int handle)
{
/* fid_t fid;
ipc_call_t call;
ipc_callid_t callid;
 
fid = fibril_create(device_client_fibril, (void *)handle);
fibril_add_ready(fid);
 
*/
return EOK;
}
 
/**
*
*/
static int driver_register(char *name)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
if (phone < 0) {
printf("Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(phone, (char *)name, str_size(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return -1;
}
 
async_set_client_connection(driver_client_connection);
 
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
/*
if (NULL == async_new_connection(callback_phonehash, 0, NULL,
driver_client_connection)) {
printf("Failed to create new fibril.\n");
async_wait_for(req, NULL);
return -1;
}
*/
async_wait_for(req, &retval);
printf("Driver '%s' registered.\n", name);
 
return phone;
}
 
static int device_get_handle(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0,
&answer);
 
retval = ipc_data_write_start(driver_phone, name, str_size(name) + 1);
 
if (retval != EOK) {
printf("Failed to send device name '%s'.\n", name);
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (NULL != handle) {
*handle = -1;
}
 
if (EOK == retval) {
if (NULL != handle) {
*handle = (int) IPC_GET_ARG1(answer);
}
printf("Device '%s' has handle %u.\n", name,
(int) IPC_GET_ARG1(answer));
} else {
printf("Failed to get handle for device '%s'.\n", name);
}
 
return retval;
}
 
/** Register new device.
* @param driver_phone
* @param name Device name.
* @param handle Output variable. Handle to the created instance of device.
*/
static int device_register(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(driver_phone, (char *)name,
str_size(name) + 1);
 
if (retval != EOK) {
printf("Failed to send device name '%s'.\n", name);
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (NULL != handle) {
*handle = -1;
}
 
if (EOK == retval) {
if (NULL != handle) {
*handle = (int) IPC_GET_ARG1(answer);
}
printf("Device registered with handle %u.\n",
(int) IPC_GET_ARG1(answer));
}
 
return retval;
}
 
/** Test DevMap from the driver's point of view.
*
*
*/
char * test_devmap1(bool quiet)
{
int driver_phone;
int dev1_handle;
int dev2_handle;
int dev3_handle;
int handle;
 
/* Register new driver */
driver_phone = driver_register("TestDriver");
 
if (driver_phone < 0) {
return "Error: Cannot register driver.\n";
}
 
/* Register new device dev1*/
if (EOK != device_register(driver_phone, TEST_DEVICE1, &dev1_handle)) {
ipc_hangup(driver_phone);
return "Error: cannot register device.\n";
}
 
/* Get handle for dev2 (Should fail unless device is already
* registered by someone else)
*/
if (EOK == device_get_handle(driver_phone, TEST_DEVICE2, &handle)) {
ipc_hangup(driver_phone);
return "Error: got handle for dev2 before it was registered.\n";
}
 
/* Register new device dev2*/
if (EOK != device_register(driver_phone, TEST_DEVICE2, &dev2_handle)) {
ipc_hangup(driver_phone);
return "Error: cannot register device dev2.\n";
}
 
/* Register again device dev1 */
if (EOK == device_register(driver_phone, TEST_DEVICE1, &dev3_handle)) {
return "Error: dev1 registered twice.\n";
}
 
/* Get handle for dev1*/
if (EOK != device_get_handle(driver_phone, TEST_DEVICE1, &handle)) {
ipc_hangup(driver_phone);
return "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n";
}
 
if (handle != dev1_handle) {
ipc_hangup(driver_phone);
return "Error: cannot get handle for 'DEVMAP_DEVICE1'.\n";
}
 
if (EOK != device_client(dev1_handle)) {
ipc_hangup(driver_phone);
return "Error: failed client test for 'DEVMAP_DEVICE1'.\n";
}
 
/* TODO: */
 
ipc_hangup(driver_phone);
 
return NULL;
}
 
char *test_devmap2(bool quiet)
{
/*TODO: Full automatic test */
return NULL;
}
 
char *test_devmap3(bool quiet)
{
/* TODO: allow user to call test functions in random order */
return NULL;
}
 
/branches/dynload/uspace/app/tester/devmap/devmap1.def
0,0 → 1,6
{
"devmap1",
"DevMap test",
&test_devmap1,
true
},
/branches/dynload/uspace/app/tester/print/print2.def
File deleted
/branches/dynload/uspace/app/tester/print/print3.def
File deleted
/branches/dynload/uspace/app/tester/print/print2.c
File deleted
/branches/dynload/uspace/app/tester/print/print3.c
File deleted
/branches/dynload/uspace/app/tester/print/print4.c
30,54 → 30,63
#include <unistd.h>
#include "../tester.h"
 
char *test_print4(void)
#define PRIx8 "x"
 
char *test_print4(bool quiet)
{
TPRINTF("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n");
uint8_t group;
for (group = 1; group < 4; group++) {
TPRINTF("%#x: ", group << 5);
if (!quiet) {
printf("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n");
uint8_t index;
for (index = 0; index < 32; index++)
TPRINTF("%c", (char) ((group << 5) + index));
uint8_t group;
for (group = 1; group < 4; group++) {
printf("%#" PRIx8 ": ", group << 5);
uint8_t index;
for (index = 0; index < 32; index++)
printf("%c", (char) ((group << 5) + index));
printf(" ");
for (index = 0; index < 32; index++)
printf("%lc", (wchar_t) ((group << 5) + index));
printf("\n");
}
TPRINTF(" ");
for (index = 0; index < 32; index++)
TPRINTF("%lc", (wchar_t) ((group << 5) + index));
printf("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n");
TPRINTF("\n");
}
TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n");
for (group = 4; group < 8; group++) {
TPRINTF("%#x: ", group << 5);
for (group = 4; group < 8; group++) {
printf("%#" PRIx8 ": ", group << 5);
uint8_t index;
for (index = 0; index < 32; index++)
printf("%lc", (wchar_t) ((group << 5) + index));
printf("\n");
}
uint8_t index;
for (index = 0; index < 32; index++)
TPRINTF("%lc", (wchar_t) ((group << 5) + index));
printf("\nUTF-8 strings using printf(\"%%s\"):\n");
printf("English: %s\n", "Quick brown fox jumps over the lazy dog");
printf("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy");
printf("Greek: %s\n", "Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε");
printf("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה");
printf("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي");
printf("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой");
printf("Armenian: %s\n", "Սկսեց հրատարակվել Երուսաղեմի հայկական");
TPRINTF("\n");
printf("\nUTF-32 strings using printf(\"%%ls\"):\n");
printf("English: %ls\n", L"Quick brown fox jumps over the lazy dog");
printf("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy");
printf("Greek: %ls\n", L"Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε");
printf("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה");
printf("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي");
printf("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой");
printf("Armenian: %ls\n", L"Սկսեց հրատարակվել Երուսաղեմի հայկական");
 
printf("Test: [%d] '%lc'\n", L'\x0161', L'\x0161');
}
 
printf("[Press a key]\n");
getchar();
TPRINTF("\nUTF-8 strings using printf(\"%%s\"):\n");
TPRINTF("English: %s\n", "Quick brown fox jumps over the lazy dog");
TPRINTF("Czech: %s\n", "Příliš žluťoučký kůň úpěl ďábelské ódy");
TPRINTF("Greek: %s\n", "Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε");
TPRINTF("Hebrew: %s\n", "משוואת ברנולי היא משוואה בהידרודינמיקה");
TPRINTF("Arabic: %s\n", "التوزيع الجغرافي للحمل العنقودي");
TPRINTF("Russian: %s\n", "Леннон познакомился с художницей-авангардисткой");
TPRINTF("Armenian: %s\n", "Սկսեց հրատարակվել Երուսաղեմի հայկական");
TPRINTF("\nUTF-32 strings using printf(\"%%ls\"):\n");
TPRINTF("English: %ls\n", L"Quick brown fox jumps over the lazy dog");
TPRINTF("Czech: %ls\n", L"Příliš žluťoučký kůň úpěl ďábelské ódy");
TPRINTF("Greek: %ls\n", L"Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε");
TPRINTF("Hebrew: %ls\n", L"משוואת ברנולי היא משוואה בהידרודינמיקה");
TPRINTF("Arabic: %ls\n", L"التوزيع الجغرافي للحمل العنقودي");
TPRINTF("Russian: %ls\n", L"Леннон познакомился с художницей-авангардисткой");
TPRINTF("Armenian: %ls\n", L"Սկսեց հրատարակվել Երուսաղեմի հայկական");
return NULL;
}
/branches/dynload/uspace/app/tester/print/print1.def
1,6 → 1,6
{
"print1",
"String printf test",
"Printf test",
&test_print1,
true
},
/branches/dynload/uspace/app/tester/print/print1.c
30,27 → 30,44
#include <unistd.h>
#include "../tester.h"
 
char *test_print1(void)
#define BUFFER_SIZE 32
 
char * test_print1(bool quiet)
{
TPRINTF("Testing printf(\"%%*.*s\", 5, 3, \"text\"):\n");
TPRINTF("Expected output: \" tex\"\n");
TPRINTF("Real output: \"%*.*s\"\n\n", 5, 3, "text");
if (!quiet) {
int retval;
unsigned int nat = 0x12345678u;
char buffer[BUFFER_SIZE];
printf(" text 10.8s %*.*s \n", 5, 3, "text");
printf(" very long text 10.8s %10.8s \n", "very long text");
printf(" text 8.10s %8.10s \n", "text");
printf(" very long text 8.10s %8.10s \n", "very long text");
printf(" char: c '%c', 3.2c '%3.2c', -3.2c '%-3.2c', 2.3c '%2.3c', -2.3c '%-2.3c' \n",'a', 'b', 'c', 'd', 'e' );
printf(" int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",1, 1, 1, 1, 1 );
printf(" -int: d '%d', 3.2d '%3.2d', -3.2d '%-3.2d', 2.3d '%2.3d', -2.3d '%-2.3d' \n",-1, -1, -1, -1, -1 );
printf(" 0xint: x '%#x', 5.3x '%#5.3x', -5.3x '%#-5.3x', 3.5x '%#3.5x', -3.5x '%#-3.5x' \n",17, 17, 17, 17, 17 );
printf("'%#llx' 64bit, '%#x' 32bit, '%#hhx' 8bit, '%#hx' 16bit, unative_t '%#zx'. '%#llx' 64bit and '%s' string.\n", 0x1234567887654321ll, 0x12345678, 0x12, 0x1234, nat, 0x1234567887654321ull, "Lovely string" );
printf(" Print to NULL '%s'\n", NULL);
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters.");
printf("Result is: '%s', retval = %d\n", buffer, retval);
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters.");
printf("Result is: '%s', retval = %d\n", buffer, retval);
printf("Print short text to %d char long buffer via snprintf.\n", BUFFER_SIZE);
retval = snprintf(buffer, BUFFER_SIZE, "Short %s", "text");
printf("Result is: '%s', retval = %d\n", buffer, retval);
printf("Print long text to %d char long buffer via snprintf.\n", BUFFER_SIZE);
retval = snprintf(buffer, BUFFER_SIZE, "Very long %s. This text`s length is more than %d. We are interested in the result.", "text" , BUFFER_SIZE);
printf("Result is: '%s', retval = %d\n", buffer, retval);
}
TPRINTF("Testing printf(\"%%10.8s\", \"very long text\"):\n");
TPRINTF("Expected output: \" very lon\"\n");
TPRINTF("Real output: \"%10.8s\"\n\n", "very long text");
TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n");
TPRINTF("Expected output: \"text\"\n");
TPRINTF("Real output: \"%8.10s\"\n\n", "text");
TPRINTF("Testing printf(\"%%8.10s\", \"very long text\"):\n");
TPRINTF("Expected output: \"very long \"\n");
TPRINTF("Real output: \"%8.10s\"\n\n", "very long text");
TPRINTF("Testing printf(\"%%s\", NULL):\n");
TPRINTF("Expected output: \"(NULL)\"\n");
TPRINTF("Real output: \"%s\"\n\n", NULL);
return NULL;
}
/branches/dynload/uspace/app/tester/vfs/vfs1.c
34,118 → 34,109
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <devmap.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "../tester.h"
 
#define FS_TYPE "tmpfs"
#define MOUNT_POINT "/tmp"
#define OPTIONS ""
#define FLAGS 0
char text[] = "O xein', angellein Lakedaimoniois hoti teide "
"keimetha tois keinon rhemasi peithomenoi.";
 
#define TEST_DIRECTORY MOUNT_POINT "/testdir"
#define TEST_FILE TEST_DIRECTORY "/testfile"
#define TEST_FILE2 TEST_DIRECTORY "/nextfile"
 
#define MAX_DEVICE_NAME 32
#define BUF_SIZE 16
 
static char text[] = "Lorem ipsum dolor sit amet, consectetur adipisicing elit";
 
static char *read_root(void)
char *test_vfs1(bool quiet)
{
TPRINTF("Opening the root directory...");
DIR *dirp = opendir("/");
if (!dirp) {
TPRINTF("\n");
return "opendir() failed";
} else
TPRINTF("OK\n");
struct dirent *dp;
while ((dp = readdir(dirp)))
TPRINTF(" node \"%s\"\n", dp->d_name);
closedir(dirp);
return NULL;
}
int rc;
 
char *test_vfs1(void)
{
if (mkdir(MOUNT_POINT, 0) != 0)
return "mkdir() failed";
TPRINTF("Created directory %s\n", MOUNT_POINT);
char null[MAX_DEVICE_NAME];
int null_id = devmap_null_create();
if (null_id == -1)
return "Unable to create null device";
snprintf(null, MAX_DEVICE_NAME, "null%d", null_id);
int rc = mount(FS_TYPE, MOUNT_POINT, null, OPTIONS, FLAGS);
rc = mount("tmpfs", "/", "nulldev0", "", 0);
switch (rc) {
case EOK:
TPRINTF("Mounted /dev/%s as %s on %s\n", null, FS_TYPE, MOUNT_POINT);
if (!quiet)
printf("mounted tmpfs on /\n");
break;
case EBUSY:
TPRINTF("(INFO) Filesystem already mounted on %s\n", MOUNT_POINT);
if (!quiet)
printf("(INFO) something is already mounted on /\n");
break;
default:
TPRINTF("(ERR) IPC returned errno %d (is tmpfs loaded?)\n", rc);
return "mount() failed";
if (!quiet)
printf("(INFO) IPC returned errno %d\n", rc);
return "mount() failed.";
}
 
if (mkdir("/mydir", 0) != 0)
return "mkdir() failed.\n";
if (!quiet)
printf("created directory /mydir\n");
if (mkdir(TEST_DIRECTORY, 0) != 0)
return "mkdir() failed";
TPRINTF("Created directory %s\n", TEST_DIRECTORY);
int fd0 = open(TEST_FILE, O_CREAT);
int fd0 = open("/mydir/myfile", O_CREAT);
if (fd0 < 0)
return "open() failed";
TPRINTF("Created file %s (fd=%d)\n", TEST_FILE, fd0);
return "open() failed.\n";
if (!quiet)
printf("created file /mydir/myfile, fd=%d\n", fd0);
 
ssize_t cnt;
size_t size = sizeof(text);
ssize_t cnt = write(fd0, text, size);
cnt = write(fd0, text, size);
if (cnt < 0)
return "write() failed";
TPRINTF("Written %d bytes\n", cnt);
return "write() failed.\n";
if (!quiet)
printf("written %d bytes, fd=%d\n", cnt, fd0);
if (lseek(fd0, 0, SEEK_SET) != 0)
return "lseek() failed";
TPRINTF("Sought to position 0\n");
char buf[BUF_SIZE];
while ((cnt = read(fd0, buf, BUF_SIZE))) {
return "lseek() failed.\n";
if (!quiet)
printf("sought to position 0, fd=%d\n", fd0);
 
char buf[10];
 
while ((cnt = read(fd0, buf, sizeof(buf)))) {
if (cnt < 0)
return "read() failed";
TPRINTF("Read %d bytes: \".*s\"\n", cnt, cnt, buf);
return "read() failed.\n";
if (!quiet)
printf("read %d bytes: \"%.*s\", fd=%d\n", cnt, cnt,
buf, fd0);
}
 
close(fd0);
 
DIR *dirp;
struct dirent *dp;
 
if (!quiet)
printf("scanning the root directory...\n");
 
dirp = opendir("/");
if (!dirp)
return "opendir() failed\n";
while ((dp = readdir(dirp)))
printf("discovered node %s in /\n", dp->d_name);
closedir(dirp);
 
if (rename("/mydir/myfile", "/mydir/yourfile"))
return "rename() failed.\n";
 
if (!quiet)
printf("renamed /mydir/myfile to /mydir/yourfile\n");
 
if (unlink("/mydir/yourfile"))
return "unlink() failed.\n";
char *rv = read_root();
if (rv != NULL)
return rv;
if (!quiet)
printf("unlinked file /mydir/yourfile\n");
 
if (rmdir("/mydir"))
return "rmdir() failed.\n";
 
if (!quiet)
printf("removed directory /mydir\n");
if (rename(TEST_FILE, TEST_FILE2))
return "rename() failed";
TPRINTF("Renamed %s to %s\n", TEST_FILE, TEST_FILE2);
if (unlink(TEST_FILE2))
return "unlink() failed";
TPRINTF("Unlinked %s\n", TEST_FILE2);
if (rmdir(TEST_DIRECTORY))
return "rmdir() failed";
TPRINTF("Removed directory %s\n", TEST_DIRECTORY);
rv = read_root();
if (rv != NULL)
return rv;
if (!quiet)
printf("scanning the root directory...\n");
 
dirp = opendir("/");
if (!dirp)
return "opendir() failed\n";
while ((dp = readdir(dirp)))
printf("discovered node %s in /\n", dp->d_name);
closedir(dirp);
 
return NULL;
}
 
/branches/dynload/uspace/app/tester/console/console1.c
28,13 → 28,12
 
#include <stdio.h>
#include <stdlib.h>
#include <io/console.h>
#include <io/color.h>
#include <io/style.h>
#include <vfs/vfs.h>
#include <io/stream.h>
#include <async.h>
#include "../tester.h"
 
#include <console.h>
 
const char *color_name[] = {
[COLOR_BLACK] = "black",
[COLOR_BLUE] = "blue",
46,78 → 45,65
[COLOR_WHITE] = "white"
};
 
char *test_console1(void)
char * test_console1(bool quiet)
{
if (!test_quiet) {
printf("Style test: ");
fflush(stdout);
console_set_style(fphone(stdout), STYLE_NORMAL);
printf("normal ");
fflush(stdout);
console_set_style(fphone(stdout), STYLE_EMPHASIS);
printf("emphasized");
fflush(stdout);
console_set_style(fphone(stdout), STYLE_NORMAL);
printf(".\n");
unsigned int i;
unsigned int j;
printf("\nForeground color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
fflush(stdout);
console_set_color(fphone(stdout), i, COLOR_WHITE,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
int i, j;
 
printf("Style test: ");
console_set_style(STYLE_NORMAL);
printf("normal ");
console_set_style(STYLE_EMPHASIS);
printf("emphasized");
console_set_style(STYLE_NORMAL);
printf(".\n");
 
printf("Foreground color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
console_set_color(i, COLOR_WHITE,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
printf("\nBackground color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
fflush(stdout);
console_set_color(fphone(stdout), COLOR_WHITE, i,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
}
printf("\nRGB colors test:\n");
for (i = 0; i < 255; i += 16) {
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xffffff, i << 16);
putchar('X');
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
for (i = 0; i < 255; i += 16) {
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8);
putchar('X');
}
 
printf("Background color test:\n");
for (j = 0; j < 2; j++) {
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
console_set_color(COLOR_WHITE, i,
j ? CATTR_BRIGHT : 0);
printf(" %s ", color_name[i]);
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
for (i = 0; i < 255; i += 16) {
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xffffff, i);
putchar('X');
}
fflush(stdout);
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
}
 
printf("Now let's test RGB colors:\n");
 
for (i = 0; i < 255; i += 16) {
console_set_rgb_color(0xffffff, i << 16);
putchar('X');
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
for (i = 0; i < 255; i += 16) {
console_set_rgb_color(0xffffff, i << 8);
putchar('X');
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
for (i = 0; i < 255; i += 16) {
console_set_rgb_color(0xffffff, i);
putchar('X');
}
console_set_color(COLOR_BLACK, COLOR_WHITE, 0);
putchar('\n');
 
printf("[press a key]\n");
getchar();
 
return NULL;
}
/branches/dynload/uspace/app/tester/stdio/stdio2.c
31,53 → 31,39
#include <errno.h>
#include "../tester.h"
 
char *test_stdio2(void)
char * test_stdio2(bool quiet)
{
FILE *file;
FILE *f;
char *file_name = "/test";
TPRINTF("Open file \"%s\" for writing...", file_name);
size_t n;
int c;
 
printf("Open file '%s' for writing\n", file_name);
errno = 0;
file = fopen(file_name, "wt");
if (file == NULL) {
TPRINTF("errno = %d\n", errno);
return "Failed opening file";
} else
TPRINTF("OK\n");
TPRINTF("Write to file...");
fprintf(file, "integer: %u, string: \"%s\"", 42, "Hello!");
TPRINTF("OK\n");
TPRINTF("Close...");
if (fclose(file) != 0) {
TPRINTF("errno = %d\n", errno);
return "Failed closing file";
} else
TPRINTF("OK\n");
TPRINTF("Open file \"%s\" for reading...", file_name);
file = fopen(file_name, "rt");
if (file == NULL) {
TPRINTF("errno = %d\n", errno);
return "Failed opening file";
} else
TPRINTF("OK\n");
TPRINTF("File contains:\n");
f = fopen(file_name, "wt");
 
if (f == NULL)
return "Failed opening file.";
 
fprintf(f, "Integer: %d, string: '%s'\n", 42, "Hello!");
if (fclose(f) != 0)
return "Failed closing file.";
 
printf("Open file '%s' for reading\n", file_name);
 
f = fopen(file_name, "rt");
if (f == NULL)
return "Failed opening file.";
 
printf("File contains:\n");
while (true) {
int c = fgetc(file);
if (c == EOF)
break;
TPRINTF("%c", c);
c = fgetc(f);
if (c == EOF) break;
putchar(c);
}
TPRINTF("\nClose...");
if (fclose(file) != 0) {
TPRINTF("errno = %d\n", errno);
return "Failed closing file";
} else
TPRINTF("OK\n");
 
if (fclose(f) != 0)
return "Failed closing file.";
 
return NULL;
}
/branches/dynload/uspace/app/tester/stdio/stdio1.c
31,60 → 31,55
#include <errno.h>
#include "../tester.h"
 
#define BUF_SIZE 32
 
#define BUF_SIZE 32
static char buf[BUF_SIZE + 1];
 
char *test_stdio1(void)
char * test_stdio1(bool quiet)
{
FILE *file;
FILE *f;
char *file_name = "/readme";
TPRINTF("Open file \"%s\"...", file_name);
size_t n;
int c;
 
printf("Open file '%s'\n", file_name);
errno = 0;
file = fopen(file_name, "rt");
if (file == NULL) {
TPRINTF("errno = %d\n", errno);
return "Failed opening file";
} else
TPRINTF("OK\n");
TPRINTF("Read file...");
size_t cnt = fread(buf, 1, BUF_SIZE, file);
if (ferror(file)) {
TPRINTF("errno = %d\n", errno);
fclose(file);
return "Failed reading file";
} else
TPRINTF("OK\n");
buf[cnt] = '\0';
TPRINTF("Read %u bytes, string \"%s\"\n", cnt, buf);
TPRINTF("Seek to beginning...");
if (fseek(file, 0, SEEK_SET) != 0) {
TPRINTF("errno = %d\n", errno);
fclose(file);
return "Failed seeking in file";
} else
TPRINTF("OK\n");
TPRINTF("Read using fgetc()...");
f = fopen(file_name, "rt");
 
if (f == NULL) printf("errno = %d\n", errno);
 
if (f == NULL)
return "Failed opening file.";
 
n = fread(buf, 1, BUF_SIZE, f);
if (ferror(f)) {
fclose(f);
return "Failed reading file.";
}
 
printf("Read %d bytes.\n", n);
 
buf[n] = '\0';
printf("Read string '%s'.\n", buf);
 
printf("Seek to beginning.\n");
if (fseek(f, 0, SEEK_SET) != 0) {
fclose(f);
return "Failed seeking.";
}
 
printf("Read using fgetc().\n");
while (true) {
int c = fgetc(file);
if (c == EOF)
break;
TPRINTF(".");
c = fgetc(f);
if (c == EOF) break;
 
printf("'%c'", c);
}
TPRINTF("[EOF]\n");
TPRINTF("Close...");
if (fclose(file) != 0) {
TPRINTF("errno = %d\n", errno);
return "Failed closing file";
} else
TPRINTF("OK\n");
 
printf("[EOF]\n");
printf("Closing.\n");
 
if (fclose(f) != 0)
return "Failed closing.";
 
return NULL;
}
/branches/dynload/uspace/app/tester/loop/loop1.c
30,11 → 30,12
#include <stdlib.h>
#include "../tester.h"
 
char *test_loop1(void)
char *test_loop1(bool quiet)
{
TPRINTF("Looping...");
while (true);
TPRINTF("\n");
return "Survived endless loop";
printf("Looping...\n");
while (1);
printf("Survived endless loop?!!\n");
 
return NULL;
}
 
/branches/dynload/uspace/app/tester/thread/thread1.c
27,8 → 27,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#define THREADS 20
#define DELAY 10
#define THREADS 5
 
#include <atomic.h>
#include <thread.h>
38,42 → 37,45
 
static atomic_t finish;
static atomic_t threads_finished;
static bool sh_quiet;
 
static void threadtest(void *data)
{
thread_detach(thread_get_id());
while (atomic_get(&finish))
 
while (atomic_get(&finish)) {
if (!sh_quiet)
printf("%llu ", thread_get_id());
usleep(100000);
}
atomic_inc(&threads_finished);
}
 
char *test_thread1(void)
char * test_thread1(bool quiet)
{
unsigned int i;
int total = 0;
unsigned int i, total = 0;
sh_quiet = quiet;
atomic_set(&finish, 1);
atomic_set(&threads_finished, 0);
TPRINTF("Creating threads");
for (i = 0; i < THREADS; i++) {
 
for (i = 0; i < THREADS; i++) {
if (thread_create(threadtest, NULL, "threadtest", NULL) < 0) {
TPRINTF("\nCould not create thread %u\n", i);
if (!quiet)
printf("Could not create thread %d\n", i);
break;
}
TPRINTF(".");
total++;
}
TPRINTF("\nRunning threads for %u seconds...", DELAY);
sleep(DELAY);
TPRINTF("\n");
if (!quiet)
printf("Running threads for 10 seconds...\n");
sleep(10);
atomic_set(&finish, 0);
while (atomic_get(&threads_finished) < total) {
TPRINTF("Threads left: %u\n", total - atomic_get(&threads_finished));
if (!quiet)
printf("Threads left: %d\n", total - atomic_get(&threads_finished));
sleep(1);
}
/branches/dynload/uspace/app/tester/fault/fault1.c
29,7 → 29,7
 
#include "../tester.h"
 
char *test_fault1(void)
char * test_fault1(bool quiet)
{
((int *)(0))[1] = 0;
/branches/dynload/uspace/app/tester/fault/fault2.c
29,7 → 29,7
 
#include "../tester.h"
 
char *test_fault2(void)
char * test_fault2(bool quiet)
{
volatile long long var;
volatile int var1;
/branches/dynload/uspace/app/trace/trace.c
41,13 → 41,7
#include <udebug.h>
#include <async.h>
#include <task.h>
#include <mem.h>
#include <string.h>
#include <bool.h>
#include <loader/loader.h>
#include <io/console.h>
#include <io/keycode.h>
#include <fibril_sync.h>
 
#include <libc.h>
 
68,31 → 62,22
 
int next_thread_id;
 
ipc_call_t thread_ipc_req[THBUF_SIZE];
 
int phoneid;
bool abort_trace;
int abort_trace;
 
uintptr_t thash;
static bool paused;
static fibril_condvar_t state_cv;
static fibril_mutex_t state_lock;
volatile int paused;
 
static bool cev_valid;
static console_event_t cev;
 
void thread_trace_start(uintptr_t thread_hash);
 
static proto_t *proto_console;
static task_id_t task_id;
static loader_t *task_ldr;
static bool task_wait_for;
 
/** Combination of events/data to print. */
display_mask_t display_mask;
 
static int program_run_fibril(void *arg);
static int cev_fibril(void *arg);
 
static void program_run(void)
{
107,19 → 92,6
fibril_add_ready(fid);
}
 
static void cev_fibril_start(void)
{
fid_t fid;
 
fid = fibril_create(cev_fibril, NULL);
if (fid == 0) {
printf("Error creating fibril\n");
exit(1);
}
 
fibril_add_ready(fid);
}
 
static int program_run_fibril(void *arg)
{
int rc;
206,10 → 178,6
 
void val_print(sysarg_t val, val_type_t v_type)
{
long sval;
 
sval = (long) val;
 
switch (v_type) {
case V_VOID:
printf("<void>");
216,7 → 184,7
break;
 
case V_INTEGER:
printf("%ld", sval);
printf("%ld", val);
break;
 
case V_HASH:
225,29 → 193,29
break;
 
case V_ERRNO:
if (sval >= -15 && sval <= 0) {
printf("%ld %s (%s)", sval,
err_desc[-sval].name,
err_desc[-sval].desc);
if (val >= -15 && val <= 0) {
printf("%ld %s (%s)", val,
err_desc[-val].name,
err_desc[-val].desc);
} else {
printf("%ld", sval);
printf("%ld", val);
}
break;
case V_INT_ERRNO:
if (sval >= -15 && sval < 0) {
printf("%ld %s (%s)", sval,
err_desc[-sval].name,
err_desc[-sval].desc);
if (val >= -15 && val < 0) {
printf("%ld %s (%s)", val,
err_desc[-val].name,
err_desc[-val].desc);
} else {
printf("%ld", sval);
printf("%ld", val);
}
break;
 
case V_CHAR:
if (sval >= 0x20 && sval < 0x7f) {
printf("'%c'", sval);
if (val >= 0x20 && val < 0x7f) {
printf("'%c'", val);
} else {
switch (sval) {
switch (val) {
case '\a': printf("'\\a'"); break;
case '\b': printf("'\\b'"); break;
case '\n': printf("'\\n'"); break;
286,8 → 254,7
ipc_call_t call;
ipcarg_t phoneid;
if (sc_rc == (sysarg_t) IPC_CALLRET_FATAL ||
sc_rc == (sysarg_t) IPC_CALLRET_TEMPORARY)
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
return;
 
phoneid = sc_args[0];
307,8 → 274,7
ipc_call_t call;
int rc;
 
if (sc_rc == (sysarg_t) IPC_CALLRET_FATAL ||
sc_rc == (sysarg_t) IPC_CALLRET_TEMPORARY)
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
return;
 
memset(&call, 0, sizeof(call));
347,38 → 313,22
ipcp_call_sync(phoneidx, &question, &reply);
}
 
static void sc_ipc_call_sync_slow_b(unsigned thread_id, sysarg_t *sc_args)
static void sc_ipc_call_sync_slow(sysarg_t *sc_args)
{
ipc_call_t question;
ipc_call_t question, reply;
int rc;
 
memset(&question, 0, sizeof(question));
rc = udebug_mem_read(phoneid, &question.args, sc_args[1],
sizeof(question.args));
rc = udebug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args));
printf("dmr->%d\n", rc);
if (rc < 0) return;
 
if (rc < 0) {
printf("Error: mem_read->%d\n", rc);
return;
}
 
thread_ipc_req[thread_id] = question;
}
 
static void sc_ipc_call_sync_slow_e(unsigned thread_id, sysarg_t *sc_args)
{
ipc_call_t reply;
int rc;
 
memset(&reply, 0, sizeof(reply));
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2],
sizeof(reply.args));
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args));
printf("dmr->%d\n", rc);
if (rc < 0) return;
 
if (rc < 0) {
printf("Error: mem_read->%d\n", rc);
return;
}
 
ipcp_call_sync(sc_args[0], &thread_ipc_req[thread_id], &reply);
ipcp_call_sync(sc_args[0], &question, &reply);
}
 
static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc)
423,14 → 373,6
print_sc_args(sc_args, syscall_desc[sc_id].n_args);
}
 
switch (sc_id) {
case SYS_IPC_CALL_SYNC_SLOW:
sc_ipc_call_sync_slow_b(thread_id, sc_args);
break;
default:
break;
}
 
async_serialize_end();
}
 
471,7 → 413,7
sc_ipc_call_sync_fast(sc_args);
break;
case SYS_IPC_CALL_SYNC_SLOW:
sc_ipc_call_sync_slow_e(thread_id, sc_args);
sc_ipc_call_sync_slow(sc_args);
break;
case SYS_IPC_WAIT:
sc_ipc_wait(sc_args, sc_rc);
502,26 → 444,20
 
thread_hash = (uintptr_t)thread_hash_arg;
thread_id = next_thread_id++;
if (thread_id >= THBUF_SIZE) {
printf("Too many threads.\n");
return ELIMIT;
}
 
printf("Start tracing thread [%d] (hash 0x%lx).\n", thread_id, thread_hash);
 
while (!abort_trace) {
 
fibril_mutex_lock(&state_lock);
if (paused) {
printf("Thread [%d] paused. Press R to resume.\n",
thread_id);
 
while (paused)
fibril_condvar_wait(&state_cv, &state_lock);
 
printf("Thread [%d] resumed.\n", thread_id);
printf("Press R to resume (and be patient).\n");
while (paused) {
usleep(1000000);
fibril_yield();
printf(".");
}
printf("Resumed\n");
}
fibril_mutex_unlock(&state_lock);
 
/* Run thread until an event occurs */
rc = udebug_go(phoneid, thread_hash,
543,9 → 479,6
break;
case UDEBUG_EVENT_STOP:
printf("Stop event\n");
fibril_mutex_lock(&state_lock);
paused = true;
fibril_mutex_unlock(&state_lock);
break;
case UDEBUG_EVENT_THREAD_B:
event_thread_b(val0);
552,10 → 485,7
break;
case UDEBUG_EVENT_THREAD_E:
printf("Thread 0x%lx exited.\n", val0);
fibril_mutex_lock(&state_lock);
abort_trace = true;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
abort_trace = 1;
break;
default:
printf("Unknown event type %d.\n", ev_type);
608,33 → 538,6
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)
650,32 → 553,11
return NULL;
}
 
static int cev_fibril(void *arg)
{
(void) arg;
 
while (true) {
fibril_mutex_lock(&state_lock);
while (cev_valid)
fibril_condvar_wait(&state_cv, &state_lock);
fibril_mutex_unlock(&state_lock);
 
if (!console_get_event(fphone(stdin), &cev))
return -1;
 
fibril_mutex_lock(&state_lock);
cev_valid = true;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
}
}
 
static void trace_task(task_id_t task_id)
{
console_event_t ev;
bool done;
int i;
int rc;
int c;
 
ipcp_init();
 
691,55 → 573,29
return;
}
 
abort_trace = false;
abort_trace = 0;
 
for (i = 0; i < n_threads; i++) {
thread_trace_start(thread_hash_buf[i]);
}
 
done = false;
 
while (!done) {
fibril_mutex_lock(&state_lock);
while (!cev_valid && !abort_trace)
fibril_condvar_wait(&state_cv, &state_lock);
fibril_mutex_unlock(&state_lock);
 
ev = cev;
 
fibril_mutex_lock(&state_lock);
cev_valid = false;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
 
if (abort_trace)
break;
 
if (ev.type != KEY_PRESS)
continue;
 
switch (ev.key) {
case KC_Q:
done = true;
break;
case KC_P:
while(1) {
c = getchar();
if (c == 'q') break;
if (c == 'p') {
printf("Pause...\n");
paused = 1;
rc = udebug_stop(phoneid, thash);
if (rc != EOK)
printf("Error: stop -> %d\n", rc);
break;
case KC_R:
fibril_mutex_lock(&state_lock);
paused = false;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
printf("stop -> %d\n", rc);
}
if (c == 'r') {
paused = 0;
printf("Resume...\n");
break;
}
}
 
printf("\nTerminate debugging session...\n");
abort_trace = true;
abort_trace = 1;
udebug_end(phoneid);
ipc_hangup(phoneid);
 
771,58 → 627,47
};
 
next_thread_id = 1;
paused = false;
cev_valid = false;
paused = 0;
 
fibril_mutex_initialize(&state_lock);
fibril_condvar_initialize(&state_cv);
 
proto_init();
 
p = proto_new("vfs");
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_OPEN, o);
o = oper_new("open_node", 4, arg_def, V_INT_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_OPEN_NODE, o);
o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_IN_READ, o);
proto_add_oper(p, VFS_READ, o);
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_IN_WRITE, o);
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_SEEK, o);
proto_add_oper(p, VFS_WRITE, o);
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_TRUNCATE, o);
o = oper_new("fstat", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_FSTAT, o);
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_CLOSE, o);
proto_add_oper(p, VFS_TRUNCATE, o);
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_MOUNT, o);
proto_add_oper(p, VFS_MOUNT, o);
/* o = oper_new("unmount", 0, arg_def);
proto_add_oper(p, VFS_IN_UNMOUNT, o);*/
o = oper_new("sync", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_SYNC, o);
proto_add_oper(p, VFS_UNMOUNT, o);*/
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_OPEN, o);
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_CLOSE, o);
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_SEEK, o);
o = oper_new("mkdir", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_MKDIR, o);
proto_add_oper(p, VFS_MKDIR, o);
o = oper_new("unlink", 0, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_UNLINK, o);
proto_add_oper(p, VFS_UNLINK, o);
o = oper_new("rename", 0, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_RENAME, o);
o = oper_new("stat", 0, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_STAT, o);
proto_add_oper(p, VFS_RENAME, o);
 
proto_register(SERVICE_VFS, p);
 
p = proto_new("console");
 
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_IN_WRITE, o);
 
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
resp_def[2] = V_INTEGER; resp_def[3] = V_CHAR;
o = oper_new("getkey", 0, arg_def, V_ERRNO, 4, resp_def);
proto_add_oper(p, CONSOLE_GETKEY, o);
 
arg_def[0] = V_CHAR;
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_PUTCHAR, o);
o = oper_new("write", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_WRITE, o);
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_CLEAR, o);
 
832,7 → 677,9
 
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
o = oper_new("getsize", 0, arg_def, V_INTEGER, 2, resp_def);
proto_add_oper(p, CONSOLE_GET_SIZE, o);
proto_add_oper(p, CONSOLE_GETSIZE, o);
o = oper_new("flush", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_FLUSH, o);
 
arg_def[0] = V_INTEGER;
o = oper_new("set_style", 1, arg_def, V_VOID, 0, resp_def);
910,7 → 757,6
--argc; ++argv;
task_id = strtol(*argv, &err_p, 10);
task_ldr = NULL;
task_wait_for = false;
if (*err_p) {
printf("Task ID syntax error\n");
print_syntax();
948,7 → 794,6
while (*cp) printf("'%s'\n", *cp++);
}
task_ldr = preload_task(*argv, argv, &task_id);
task_wait_for = true;
 
return 0;
}
956,8 → 801,6
int main(int argc, char *argv[])
{
int rc;
task_exit_t texit;
int retval;
 
printf("System Call / IPC Tracer\n");
printf("Controls: Q - Quit, P - Pause, R - Resume\n");
977,29 → 820,12
 
printf("Connected to task %lld.\n", task_id);
 
if (task_ldr != NULL)
if (task_ldr != NULL) {
program_run();
}
 
cev_fibril_start();
trace_task(task_id);
 
if (task_wait_for) {
printf("Waiting for task to exit.\n");
 
rc = task_wait(task_id, &texit, &retval);
if (rc != EOK) {
printf("Failed waiting for task.\n");
return -1;
}
 
if (texit == TASK_EXIT_NORMAL) {
printf("Task exited normally, return value %d.\n",
retval);
} else {
printf("Task exited unexpectedly.\n");
}
}
 
return 0;
}
 
/branches/dynload/uspace/app/trace/proto.c
35,7 → 35,7
#include <stdio.h>
#include <stdlib.h>
#include <ipc/ipc.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
#include "trace.h"
#include "proto.h"
46,7 → 46,7
hash_table_t srv_proto;
 
typedef struct {
unsigned srv;
int srv;
proto_t *proto;
link_t link;
} srv_proto_t;
/branches/dynload/uspace/app/trace/proto.h
35,7 → 35,7
#ifndef PROTO_H_
#define PROTO_H_
 
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
#include <ipc/ipc.h>
#include "trace.h"
 
/branches/dynload/uspace/app/trace/ipcp.c
34,7 → 34,7
 
#include <stdio.h>
#include <stdlib.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
#include "ipc_desc.h"
#include "proto.h"
/branches/dynload/uspace/app/dload/dload.c
38,8 → 38,7
#include <unistd.h>
#include <fcntl.h>
#include <loader/pcb.h>
#include <ipc/ipc.h>
#include <vfs/vfs.h>
#include <console.h>
 
/* from librtld */
#include <rtld.h>
108,7 → 107,7
DPRINTF("Run program.. (at 0x%lx)\n", (uintptr_t)__pcb->entry);
 
#ifndef RTLD_DEBUG
ipc_hangup(fphone(stdout));
console_close();
#endif
program_run(__pcb->entry, __pcb);
 
/branches/dynload/uspace/app/tetris/Makefile
26,7 → 26,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/app/tetris/scores.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
48,18 → 48,24
*
* Major whacks since then.
*/
 
#include <errno.h>
/* #include <err.h> */
/* #include <fcntl.h> */
/* #include <pwd.h> */
#include <stdio.h>
/* #include <stdlib.h> */
#include <string.h>
#include <io/console.h>
#include <io/keycode.h>
#include <vfs/vfs.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <stdlib.h>
#include <fcntl.h>
#include <err.h>
#include <time.h>
/* #include <time.h> */
/* #include <term.h> */
/* #include <unistd.h> */
/* #include <sys/param.h> */
/* #include <sys/stat.h> */
/* #include <sys/types.h> */
 
#include "pathnames.h"
#include "screen.h"
#include "tetris.h"
#include "scores.h"
72,22 → 78,20
* As long as the scores are kept sorted, this is simply the first one at
* that level.
*/
#define NUMSPOTS (MAXHISCORES + 1)
#define NLEVELS (MAXLEVEL + 1)
 
#define NUMSPOTS (MAXHISCORES + 1)
#define NLEVELS (MAXLEVEL + 1)
 
/* static time_t now; */
/* static int nscores; */
/* static int gotscores; */
/* static struct highscore scores[NUMSPOTS]; */
static struct highscore scores[NUMSPOTS];
 
/** Copy from hiscore table score with index src to dest
*
*/
static void copyhiscore(int dest, int src)
{
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
scores[src].hs_name);
scores[dest].hs_score = scores[src].hs_score;
scores[dest].hs_level = scores[src].hs_level;
}
/* static int checkscores(struct highscore *, int); */
/* static int cmpscores(const void *, const void *); */
/* static void getscores(FILE **); */
/* static void printem(int, int, struct highscore *, int, const char *); */
/* static char *thisuser(void); */
 
void showscores(int firstgame)
{
97,55 → 101,59
moveto(10, 0);
printf("\tRank \tLevel \tName\t points\n");
printf("\t========================================================\n");
for (i = 0; i < NUMSPOTS - 1; i++)
printf("\t%6d %6d %-16s %20d\n",
i + 1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
for (i = 0; i < NUMSPOTS - 1; i++) {
printf("\t%6d %6d %-16s %20d\n", i+1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
}
if (!firstgame) {
printf("\t========================================================\n");
printf("\t Last %6d %-16s %20d\n",
scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
printf("\t Last %6d %-16s %20d\n", scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
}
printf("\n\n\n\n\tPress any key to return to main menu.");
getchar();
}
 
/** Copy from hiscore table score with index src to dest
*
*/
static void copyhiscore(int dest, int src)
{
str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
scores[src].hs_name);
scores[dest].hs_score = scores[src].hs_score;
scores[dest].hs_level = scores[src].hs_level;
}
 
void insertscore(int score, int level)
{
int i;
int j;
int i,j;
size_t off;
console_event_t ev;
kbd_event_t ev;
clear_screen();
moveto(10, 10);
moveto(10 , 10);
puts("Insert your name: ");
str_cpy(scores[NUMSPOTS - 1].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
"Player");
i = 6;
off = 6;
i = 6; off = 6;
 
moveto(10 , 28);
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME-i,
"........................................");
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
 
while (1) {
fflush(stdout);
if (!console_get_event(fphone(stdin), &ev))
if (kbd_get_event(&ev) != EOK)
exit(1);
if (ev.type == KEY_RELEASE)
 
if (ev.type == KE_RELEASE)
continue;
 
if (ev.key == KC_ENTER || ev.key == KC_NENTER)
break;
 
if (ev.key == KC_BACKSPACE) {
if (i > 0) {
wchar_t uc;
 
--i;
while (off > 0) {
--off;
155,7 → 163,7
if (uc != U_SPECIAL)
break;
}
 
scores[NUMSPOTS - 1].hs_name[off] = '\0';
}
} else if (ev.c != '\0') {
168,66 → 176,398
}
}
moveto(10, 28);
printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME - i,
"........................................");
moveto(10 , 28);
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
}
scores[NUMSPOTS - 1].hs_score = score;
scores[NUMSPOTS - 1].hs_score = score;
scores[NUMSPOTS - 1].hs_level = level;
i = NUMSPOTS - 1;
i = NUMSPOTS-1;
while ((i > 0) && (scores[i - 1].hs_score < score))
i--;
for (j = NUMSPOTS - 2; j > i; j--)
copyhiscore(j, j-1);
copyhiscore(i, NUMSPOTS - 1);
 
for (j = NUMSPOTS - 2; j > i; j--) {
copyhiscore(j,j-1);
}
copyhiscore(i, NUMSPOTS - 1);
}
 
void initscores(void)
{
int i;
for (i = 0; i < NUMSPOTS; i++) {
for(i = 0; i < NUMSPOTS; i++) {
str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team");
scores[i].hs_score = (NUMSPOTS - i) * 200;
scores[i].hs_level = (i + 1 > MAXLEVEL ? MAXLEVEL : i + 1);
scores[i].hs_score = (NUMSPOTS - i) * 200;
scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1);
}
}
 
int loadscores(void)
{
FILE *f;
size_t cnt;
int rc;
/*
* Read the score file. Can be called from savescore (before showscores)
* or showscores (if savescore will not be called). If the given pointer
* is not NULL, sets *fpp to an open file pointer that corresponds to a
* read/write score file that is locked with LOCK_EX. Otherwise, the
* file is locked with LOCK_SH for the read and closed before return.
*
* Note, we assume closing the stdio file releases the lock.
*/
/* static void */
/* getscores(FILE **fpp) */
/* { */
/* int sd, mint, lck, mask, i; */
/* char *mstr, *human; */
/* FILE *sf; */
 
f = fopen("/data/tetris.sco", "rb");
if (f == NULL)
return ENOENT;
/* if (fpp != NULL) { */
/* mint = O_RDWR | O_CREAT; */
/* mstr = "r+"; */
/* human = "read/write"; */
/* lck = LOCK_EX; */
/* } else { */
/* mint = O_RDONLY; */
/* mstr = "r"; */
/* human = "reading"; */
/* lck = LOCK_SH; */
/* } */
/* setegid(egid); */
/* mask = umask(S_IWOTH); */
/* sd = open(_PATH_SCOREFILE, mint, 0666); */
/* (void)umask(mask); */
/* setegid(gid); */
/* if (sd < 0) { */
/* if (fpp == NULL) { */
/* nscores = 0; */
/* return; */
/* } */
/* err(1, "cannot open %s for %s", _PATH_SCOREFILE, human); */
/* } */
/* setegid(egid); */
/* if ((sf = fdopen(sd, mstr)) == NULL) */
/* err(1, "cannot fdopen %s for %s", _PATH_SCOREFILE, human); */
/* setegid(gid); */
 
cnt = fread(scores, sizeof(struct highscore), NUMSPOTS, f);
rc = fclose(f);
/* /\* */
/* * Grab a lock. */
/* *\/ */
/* if (flock(sd, lck)) */
/* warn("warning: score file %s cannot be locked", */
/* _PATH_SCOREFILE); */
 
if (cnt != NUMSPOTS || rc != 0)
return EIO;
/* nscores = fread(scores, sizeof(scores[0]), MAXHISCORES, sf); */
/* if (ferror(sf)) */
/* err(1, "error reading %s", _PATH_SCOREFILE); */
/* for (i = 0; i < nscores; i++) */
/* if (scores[i].hs_level < MINLEVEL || */
/* scores[i].hs_level > MAXLEVEL) */
/* errx(1, "scorefile %s corrupt", _PATH_SCOREFILE); */
 
return EOK;
}
/* if (fpp) */
/* *fpp = sf; */
/* else */
/* (void)fclose(sf); */
/* } */
 
void savescores(void)
void
savescore(int level)
{
FILE *f;
size_t cnt;
int rc;
return;
}
/* struct highscore *sp; */
/* int i; */
/* int change; */
/* FILE *sf; */
/* const char *me; */
 
f = fopen("/data/tetris.sco", "wb");
cnt = fwrite(scores, sizeof(struct highscore), NUMSPOTS, f);
rc = fclose(f);
/* getscores(&sf); */
/* gotscores = 1; */
/* (void)time(&now); */
 
if (cnt != NUMSPOTS || rc != 0)
printf("Error saving score table\n");
/* /\* */
/* * Allow at most one score per person per level -- see if we */
/* * can replace an existing score, or (easiest) do nothing. */
/* * Otherwise add new score at end (there is always room). */
/* *\/ */
/* change = 0; */
/* me = thisuser(); */
/* for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */
/* if (sp->hs_level != level || str_cmp(sp->hs_name, me) != 0) */
/* continue; */
/* if (score > sp->hs_score) { */
/* (void)printf("%s bettered %s %d score of %d!\n", */
/* "\nYou", "your old level", level, */
/* sp->hs_score * sp->hs_level); */
/* sp->hs_score = score; /\* new score *\/ */
/* sp->hs_time = now; /\* and time *\/ */
/* change = 1; */
/* } else if (score == sp->hs_score) { */
/* (void)printf("%s tied %s %d high score.\n", */
/* "\nYou", "your old level", level); */
/* sp->hs_time = now; /\* renew it *\/ */
/* change = 1; /\* gotta rewrite, sigh *\/ */
/* } /\* else new score < old score: do nothing *\/ */
/* break; */
/* } */
/* if (i >= nscores) { */
/* strlcpy(sp->hs_name, me, sizeof sp->hs_name); */
/* sp->hs_level = level; */
/* sp->hs_score = score; */
/* sp->hs_time = now; */
/* nscores++; */
/* change = 1; */
/* } */
 
/* if (change) { */
/* /\* */
/* * Sort & clean the scores, then rewrite. */
/* *\/ */
/* nscores = checkscores(scores, nscores); */
/* rewind(sf); */
/* if (fwrite(scores, sizeof(*sp), nscores, sf) != nscores || */
/* fflush(sf) == EOF) */
/* warnx("error writing %s: %s\n\t-- %s", */
/* _PATH_SCOREFILE, strerror(errno), */
/* "high scores may be damaged"); */
/* } */
/* (void)fclose(sf); /\* releases lock *\/ */
/* } */
 
/*
* Get login name, or if that fails, get something suitable.
* The result is always trimmed to fit in a score.
*/
/* static char * */
/* thisuser(void) */
/* { */
/* const char *p; */
/* struct passwd *pw; */
/* static char u[sizeof(scores[0].hs_name)]; */
 
/* if (u[0]) */
/* return (u); */
/* p = getlogin(); */
/* if (p == NULL || *p == '\0') { */
/* pw = getpwuid(getuid()); */
/* if (pw != NULL) */
/* p = pw->pw_name; */
/* else */
/* p = " ???"; */
/* } */
/* strlcpy(u, p, sizeof(u)); */
/* return (u); */
/* } */
 
/*
* Score comparison function for qsort.
*
* If two scores are equal, the person who had the score first is
* listed first in the highscore file.
*/
/* static int */
/* cmpscores(const void *x, const void *y) */
/* { */
/* const struct highscore *a, *b; */
/* long l; */
 
/* a = x; */
/* b = y; */
/* l = (long)b->hs_level * b->hs_score - (long)a->hs_level * a->hs_score; */
/* if (l < 0) */
/* return (-1); */
/* if (l > 0) */
/* return (1); */
/* if (a->hs_time < b->hs_time) */
/* return (-1); */
/* if (a->hs_time > b->hs_time) */
/* return (1); */
/* return (0); */
/* } */
 
/*
* If we've added a score to the file, we need to check the file and ensure
* that this player has only a few entries. The number of entries is
* controlled by MAXSCORES, and is to ensure that the highscore file is not
* monopolised by just a few people. People who no longer have accounts are
* only allowed the highest score. Scores older than EXPIRATION seconds are
* removed, unless they are someone's personal best.
* Caveat: the highest score on each level is always kept.
*/
/* static int */
/* checkscores(struct highscore *hs, int num) */
/* { */
/* struct highscore *sp; */
/* int i, j, k, numnames; */
/* int levelfound[NLEVELS]; */
/* struct peruser { */
/* char *name; */
/* int times; */
/* } count[NUMSPOTS]; */
/* struct peruser *pu; */
 
/* /\* */
/* * Sort so that highest totals come first. */
/* * */
/* * levelfound[i] becomes set when the first high score for that */
/* * level is encountered. By definition this is the highest score. */
/* *\/ */
/* qsort((void *)hs, nscores, sizeof(*hs), cmpscores); */
/* for (i = MINLEVEL; i < NLEVELS; i++) */
/* levelfound[i] = 0; */
/* numnames = 0; */
/* for (i = 0, sp = hs; i < num;) { */
/* /\* */
/* * This is O(n^2), but do you think we care? */
/* *\/ */
/* for (j = 0, pu = count; j < numnames; j++, pu++) */
/* if (str_cmp(sp->hs_name, pu->name) == 0) */
/* break; */
/* if (j == numnames) { */
/* /\* */
/* * Add new user, set per-user count to 1. */
/* *\/ */
/* pu->name = sp->hs_name; */
/* pu->times = 1; */
/* numnames++; */
/* } else { */
/* /\* */
/* * Two ways to keep this score: */
/* * - Not too many (per user), still has acct, & */
/* * score not dated; or */
/* * - High score on this level. */
/* *\/ */
/* if ((pu->times < MAXSCORES && */
/* getpwnam(sp->hs_name) != NULL && */
/* sp->hs_time + EXPIRATION >= now) || */
/* levelfound[sp->hs_level] == 0) */
/* pu->times++; */
/* else { */
/* /\* */
/* * Delete this score, do not count it, */
/* * do not pass go, do not collect $200. */
/* *\/ */
/* num--; */
/* for (k = i; k < num; k++) */
/* hs[k] = hs[k + 1]; */
/* continue; */
/* } */
/* } */
/* levelfound[sp->hs_level] = 1; */
/* i++, sp++; */
/* } */
/* return (num > MAXHISCORES ? MAXHISCORES : num); */
/* } */
 
/*
* Show current scores. This must be called after savescore, if
* savescore is called at all, for two reasons:
* - Showscores munches the time field.
* - Even if that were not the case, a new score must be recorded
* before it can be shown anyway.
*/
/*
void
showscores(int level)
{
return;
}
*/
/* struct highscore *sp; */
/* int i, n, c; */
/* const char *me; */
/* int levelfound[NLEVELS]; */
 
/* if (!gotscores) */
/* getscores((FILE **)NULL); */
/* (void)printf("\n\t\t Tetris High Scores\n"); */
 
/* /\* */
/* * If level == 0, the person has not played a game but just asked for */
/* * the high scores; we do not need to check for printing in highlight */
/* * mode. If SOstr is null, we can't do highlighting anyway. */
/* *\/ */
/* me = level && SOstr ? thisuser() : NULL; */
 
/* /\* */
/* * Set times to 0 except for high score on each level. */
/* *\/ */
/* for (i = MINLEVEL; i < NLEVELS; i++) */
/* levelfound[i] = 0; */
/* for (i = 0, sp = scores; i < nscores; i++, sp++) { */
/* if (levelfound[sp->hs_level]) */
/* sp->hs_time = 0; */
/* else { */
/* sp->hs_time = 1; */
/* levelfound[sp->hs_level] = 1; */
/* } */
/* } */
 
/* /\* */
/* * Page each screenful of scores. */
/* *\/ */
/* for (i = 0, sp = scores; i < nscores; sp += n) { */
/* n = 20; */
/* if (i + n > nscores) */
/* n = nscores - i; */
/* printem(level, i + 1, sp, n, me); */
/* if ((i += n) < nscores) { */
/* (void)printf("\nHit RETURN to continue."); */
/* (void)fflush(stdout); */
/* while ((c = getchar()) != '\n') */
/* if (c == EOF) */
/* break; */
/* (void)printf("\n"); */
/* } */
/* } */
 
/* if (nscores == 0) */
/* printf("\t\t\t - none to date.\n"); */
/* } */
 
/* static void */
/* printem(int level, int offset, struct highscore *hs, int n, const char *me) */
/* { */
/* struct highscore *sp; */
/* int row, highlight, i; */
/* char buf[100]; */
/* #define TITLE "Rank Score Name (points/level)" */
/* #define TITL2 "==========================================================" */
 
/* printf("%s\n%s\n", TITLE, TITL2); */
 
/* highlight = 0; */
 
/* for (row = 0; row < n; row++) { */
/* sp = &hs[row]; */
/* (void)snprintf(buf, sizeof(buf), */
/* "%3d%c %6d %-31s (%6d on %d)\n", */
/* row + offset, sp->hs_time ? '*' : ' ', */
/* sp->hs_score * sp->hs_level, */
/* sp->hs_name, sp->hs_score, sp->hs_level); */
/* /\* Print leaders every three lines *\/ */
/* if ((row + 1) % 3 == 0) { */
/* for (i = 0; i < sizeof(buf); i++) */
/* if (buf[i] == ' ') */
/* buf[i] = '_'; */
/* } */
/* /\* */
/* * Highlight if appropriate. This works because */
/* * we only get one score per level. */
/* *\/ */
/* if (me != NULL && */
/* sp->hs_level == level && */
/* sp->hs_score == score && */
/* str_cmp(sp->hs_name, me) == 0) { */
/* putpad(SOstr); */
/* highlight = 1; */
/* } */
/* (void)printf("%s", buf); */
/* if (highlight) { */
/* putpad(SEstr); */
/* highlight = 0; */
/* } */
/* } */
/* } */
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/input.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
57,9 → 57,9
#include "tetris.h"
 
#include <async.h>
#include <vfs/vfs.h>
#include <io/console.h>
#include <ipc/console.h>
#include <console.h>
#include <kbd/kbd.h>
 
/* return true iff the given timeval is positive */
#define TV_POS(tv) \
92,12 → 92,14
* Return 0 => no input, 1 => can read() from stdin
*
*/
int rwait(struct timeval *tvp)
int
rwait(struct timeval *tvp)
{
struct timeval starttv, endtv, *s;
static ipc_call_t charcall;
ipcarg_t rc;
int cons_phone;
 
/*
* Someday, select() will do this for us.
* Just in case that day is now, and no one has
109,15 → 111,15
s = &endtv;
} else
s = NULL;
 
if (!lastchar) {
again:
if (!getchar_inprog) {
getchar_inprog = async_send_0(fphone(stdin),
CONSOLE_GET_EVENT, &charcall);
cons_phone = console_open(true);
getchar_inprog = async_send_2(cons_phone,
CONSOLE_GETKEY, 0, 0, &charcall);
}
if (!s)
if (!s)
async_wait_for(getchar_inprog, &rc);
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) {
tvp->tv_sec = 0;
124,25 → 126,22
tvp->tv_usec = 0;
return (0);
}
getchar_inprog = 0;
if (rc)
if (rc) {
stop("end of file, help");
if (IPC_GET_ARG1(charcall) == KEY_RELEASE)
}
if (IPC_GET_ARG1(charcall) == KE_RELEASE)
goto again;
 
lastchar = IPC_GET_ARG4(charcall);
}
if (tvp) {
/* since there is input, we may not have timed out */
(void) gettimeofday(&endtv, NULL);
TV_SUB(&endtv, &starttv);
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
}
return 1;
return (1);
}
 
/*
149,10 → 148,11
* `sleep' for the current turn time (using select).
* Eat any input that might be available.
*/
void tsleep(void)
void
tsleep(void)
{
struct timeval tv;
 
tv.tv_sec = 0;
tv.tv_usec = fallrate;
while (TV_POS(&tv))
165,11 → 165,12
/*
* getchar with timeout.
*/
int tgetchar(void)
int
tgetchar(void)
{
static struct timeval timeleft;
char c;
 
/*
* Reset timeleft to fallrate whenever it is not positive.
* In any case, wait to see if there is any input. If so,
180,18 → 181,17
* Most of the hard work is done by rwait().
*/
if (!TV_POS(&timeleft)) {
faster(); /* go faster */
faster(); /* go faster */
timeleft.tv_sec = 0;
timeleft.tv_usec = fallrate;
}
if (!rwait(&timeleft))
return -1;
return (-1);
c = lastchar;
lastchar = '\0';
return ((int) (unsigned char) c);
return ((int)(unsigned char)c);
}
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/screen.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
50,26 → 50,21
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vfs/vfs.h>
#include <console.h>
 
#include <async.h>
#include "screen.h"
#include "tetris.h"
#include <io/console.h>
#include <ipc/console.h>
 
#define STOP (B_COLS - 3)
 
static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */
static int curscore;
static int isset; /* true => terminal is in game mode */
static int isset; /* true => terminal is in game mode */
 
static int use_color; /* true => use colors */
 
static const struct shape *lastshape;
 
 
/*
* putstr() is for unpadded strings (either as in termcap(5) or
* simply literal strings);
* simply literal strings);
*/
static inline void putstr(char *s)
{
77,22 → 72,19
putchar(*(s++));
}
 
static void start_standout(uint32_t color)
static void start_standout(void)
{
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0xf0f0f0,
use_color ? color : 0x000000);
console_set_rgb_color(0xf0f0f0, 0);
}
 
static void resume_normal(void)
{
fflush(stdout);
console_set_rgb_color(fphone(stdout), 0, 0xf0f0f0);
console_set_rgb_color(0, 0xf0f0f0);
}
 
void clear_screen(void)
{
console_clear(fphone(stdout));
console_clear();
moveto(0, 0);
}
 
99,20 → 91,23
/*
* Clear the screen, forgetting the current contents in the process.
*/
void scr_clear(void)
void
scr_clear(void)
{
 
resume_normal();
console_clear(fphone(stdout));
console_clear();
curscore = -1;
memset(curscreen, 0, sizeof(curscreen));
memset((char *)curscreen, 0, sizeof(curscreen));
}
 
/*
* Set up screen
*/
void scr_init(void)
void
scr_init(void)
{
console_cursor_visibility(fphone(stdout), 0);
console_cursor_visibility(0);
resume_normal();
scr_clear();
}
119,8 → 114,7
 
void moveto(int r, int c)
{
fflush(stdout);
console_goto(fphone(stdout), c, r);
console_goto(r, c);
}
 
winsize_t winsize;
127,41 → 121,25
 
static int get_display_size(winsize_t *ws)
{
return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row);
return console_get_size(&ws->ws_row, &ws->ws_col);
}
 
static int get_display_color_sup(void)
{
int rc;
int ccap;
 
rc = console_get_color_cap(fphone(stdout), &ccap);
if (rc != 0)
return 0;
 
return (ccap >= CONSOLE_CCAP_RGB);
}
 
/*
* Set up screen mode.
*/
void scr_set(void)
void
scr_set(void)
{
winsize_t ws;
Rows = 0;
Cols = 0;
 
Rows = 0, Cols = 0;
if (get_display_size(&ws) == 0) {
Rows = ws.ws_row;
Cols = ws.ws_col;
}
if (Rows < MINROWS || Cols < MINCOLS) {
char smallscr[55];
 
use_color = get_display_color_sup();
if ((Rows < MINROWS) || (Cols < MINCOLS)) {
char smallscr[55];
snprintf(smallscr, sizeof(smallscr),
"the screen is too small (must be at least %dx%d)",
MINROWS, MINCOLS);
168,7 → 146,7
stop(smallscr);
}
isset = 1;
 
scr_clear();
}
 
175,80 → 153,76
/*
* End screen mode.
*/
void scr_end(void)
void
scr_end(void)
{
console_cursor_visibility(fphone(stdout), 1);
}
 
void stop(char *why)
void
stop(char *why)
{
 
if (isset)
scr_end();
errx(1, "aborting: %s", why);
}
 
 
/*
* Update the screen.
*/
void scr_update(void)
void
scr_update(void)
{
cell *bp;
cell *sp;
cell so;
cell cur_so = 0;
int i;
int j;
int ccol;
/* Always leave cursor after last displayed point */
cell *bp, *sp;
cell so, cur_so = 0;
int i, ccol, j;
static const struct shape *lastshape;
 
/* always leave cursor after last displayed point */
curscreen[D_LAST * B_COLS - 1] = -1;
 
if (score != curscore) {
moveto(0, 0);
printf("Score: %d", score);
curscore = score;
}
/* Draw preview of next pattern */
if ((showpreview) && (nextshape != lastshape)) {
 
/* draw preview of next pattern */
if (showpreview && (nextshape != lastshape)) {
int i;
static int r = 5, c = 2;
static int r=5, c=2;
int tr, tc, t;
 
lastshape = nextshape;
/* Clean */
 
/* clean */
resume_normal();
moveto(r - 1, c - 1);
putstr(" ");
moveto(r, c - 1);
putstr(" ");
moveto(r + 1, c - 1);
putstr(" ");
moveto(r + 2, c - 1);
putstr(" ");
moveto(r - 3, c - 2);
moveto(r-1, c-1); putstr(" ");
moveto(r, c-1); putstr(" ");
moveto(r+1, c-1); putstr(" ");
moveto(r+2, c-1); putstr(" ");
 
moveto(r-3, c-2);
putstr("Next shape:");
/* Draw */
start_standout(nextshape->color);
 
/* draw */
start_standout();
moveto(r, 2 * c);
putstr(" ");
for (i = 0; i < 3; i++) {
t = c + r * B_COLS;
t += nextshape->off[i];
 
tr = t / B_COLS;
tc = t % B_COLS;
 
moveto(tr, 2*tc);
putstr(" ");
}
resume_normal();
}
 
bp = &board[D_FIRST * B_COLS];
sp = &curscreen[D_FIRST * B_COLS];
for (j = D_FIRST; j < D_LAST; j++) {
256,7 → 230,6
for (i = 0; i < B_COLS; bp++, sp++, i++) {
if (*sp == (so = *bp))
continue;
*sp = so;
if (i != ccol) {
if (cur_so) {
265,16 → 238,15
}
moveto(RTOD(j), CTOD(i));
}
if (so != cur_so) {
if (so)
start_standout(so);
start_standout();
else
resume_normal();
cur_so = so;
}
putstr(" ");
 
ccol = i + 1;
/*
* Look ahead a bit, to avoid extra motion if
284,35 → 256,33
* `unnecessarily'. Skip it all, though, if
* the next cell is a different color.
*/
if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
#define STOP (B_COLS - 3)
if (i > STOP || sp[1] != bp[1] || so != bp[1])
continue;
if (sp[2] != bp[2])
sp[1] = -1;
else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
sp[2] = -1;
sp[1] = -1;
}
}
}
if (cur_so)
resume_normal();
fflush(stdout);
fflush(stdout);
}
 
/*
* Write a message (set != 0), or clear the same message (set == 0).
* Write a message (set!=0), or clear the same message (set==0).
* (We need its length in case we have to overwrite with blanks.)
*/
void scr_msg(char *s, int set)
void
scr_msg(char *s, int set)
{
int l = str_size(s);
moveto(Rows - 2, ((Cols - l) >> 1) - 1);
if (set)
putstr(s);
else
322,3 → 292,4
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/scores.h
34,9 → 34,8
*
* @(#)scores.h 8.1 (Berkeley) 5/31/93
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
45,27 → 44,26
/*
* Tetris scores.
*/
 
#include <sys/time.h>
#include <string.h>
 
#define MAXLOGNAME 16
#define MAXHISCORES 10
#define MAXSCORES 9 /* maximum high score entries per person */
#define EXPIRATION (5L * 365 * 24 * 60 * 60)
 
#define MAXLOGNAME 16
struct highscore {
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */
int hs_score; /* raw score */
int hs_level; /* play level */
time_t hs_time; /* time at game end */
char hs_name[STR_BOUNDS(MAXLOGNAME) + 1]; /* login name */
int hs_score; /* raw score */
int hs_level; /* play level */
// time_t hs_time; /* time at game end */
};
 
extern void showscores(int);
extern void initscores(void);
extern void insertscore(int score, int level);
extern int loadscores(void);
extern void savescores(void);
#define MAXHISCORES 10
//#define MAXSCORES 9 /* maximum high score entries per person */
//#define EXPIRATION (5L * 365 * 24 * 60 * 60)
 
void savescore(int);
void showscores(int);
void insertscore(int score, int level);
void initscores(void);
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/tetris.c
36,25 → 36,30
*/
 
/** @addtogroup tetris Tetris
* @brief Tetris ported from OpenBSD
* @{
* @brief Tetris ported from OpenBSD
* @{
*/
/** @file
*/
 
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1992, 1993\n"
"\tThe Regents of the University of California. All rights reserved.\n";
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
 
/*
* Tetris (or however it is spelled).
*/
 
#include <sys/time.h>
#include <sys/types.h>
 
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
 
#include "input.h"
#include "scores.h"
61,76 → 66,66
#include "screen.h"
#include "tetris.h"
 
cell board[B_SIZE];
 
int Rows;
int Cols;
 
cell board[B_SIZE];
int Rows, Cols;
const struct shape *curshape;
const struct shape *nextshape;
long fallrate;
int score;
//gid_t gid, egid;
char key_msg[100];
int showpreview, classic;
 
long fallrate;
int score;
char key_msg[100];
int showpreview;
int classic;
static void elide(void);
static void setup_board(void);
const struct shape *randshape(void);
void onintr(int);
void usage(void);
 
static void elide(void);
static void setup_board(void);
static const struct shape *randshape(void);
 
static void usage(void);
 
static int firstgame = 1;
 
/*
* Set up the initial board. The bottom display row is completely set,
* along with another (hidden) row underneath that. Also, the left and
* Set up the initial board. The bottom display row is completely set,
* along with another (hidden) row underneath that. Also, the left and
* right edges are set.
*/
static void setup_board(void)
static void
setup_board(void)
{
int i;
cell *p = board;
cell *p;
 
p = board;
for (i = B_SIZE; i; i--)
*p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
*p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
}
 
/*
* Elide any full active rows.
*/
static void elide(void)
static void
elide(void)
{
int rows = 0;
int i;
int j;
int base;
int i, j, base;
cell *p;
 
for (i = A_FIRST; i < A_LAST; i++) {
base = i * B_COLS + 1;
p = &board[base];
for (j = B_COLS - 2; *p++ != 0;) {
if (--j <= 0) {
/* This row is to be elided */
/* this row is to be elided */
rows++;
memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
memset(&board[base], 0, B_COLS - 2);
scr_update();
tsleep();
while (--base != 0)
board[base + B_COLS] = board[base];
scr_update();
tsleep();
break;
}
}
}
switch (rows) {
case 1:
score += 10;
149,15 → 144,16
}
}
 
const struct shape *randshape(void)
const struct shape *
randshape(void)
{
const struct shape *tmp = &shapes[random() % 7];
int i;
int j = random() % 4;
const struct shape *tmp;
int i, j;
 
tmp = &shapes[random() % 7];
j = random() % 4;
for (i = 0; i < j; i++)
tmp = &shapes[classic ? tmp->rotc : tmp->rot];
tmp = &shapes[classic? tmp->rotc : tmp->rot];
return (tmp);
}
 
164,7 → 160,7
static void srandomdev(void)
{
struct timeval tv;
 
gettimeofday(&tv, NULL);
srandom(tv.tv_sec + tv.tv_usec / 100000);
}
171,43 → 167,61
 
static void tetris_menu_draw(int level)
{
clear_screen();
moveto(5, 10);
puts("Tetris\n\n");
moveto(8, 10);
printf("Level = %d (press keys 1 - 9 to change)", level);
moveto(9, 10);
printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off"));
moveto(12, 10);
printf("Press 'h' to show hiscore table.");
moveto(13, 10);
printf("Press 's' to start game.");
moveto(14, 10);
printf("Press 'q' to quit game.");
moveto(20, 10);
printf("In game controls:");
moveto(21, 0);
puts(key_msg);
clear_screen();
moveto(5,10);
puts("Tetris\n\n");
moveto(8,10);
printf("Level = %d (press keys 1 - 9 to change)",level);
moveto(9,10);
printf("Preview is %s (press 'p' to change)", (showpreview?"on ":"off"));
moveto(12,10);
printf("Press 'h' to show hiscore table.");
moveto(13,10);
printf("Press 's' to start game.");
moveto(14,10);
printf("Press 'q' to quit game.");
moveto(20,10);
printf("In game controls:");
moveto(21,0);
puts(key_msg);
}
 
static int tetris_menu(int *level)
static int tetris_menu(int *level)
{
static int firstgame = 1;
int i;
/* if (showpreview == 0)
(void)printf("Your score: %d point%s x level %d = %d\n",
score, score == 1 ? "" : "s", level, score * level);
else {
(void)printf("Your score: %d point%s x level %d x preview penalty %0.3f = %d\n",
score, score == 1 ? "" : "s", level, (double)PRE_PENALTY,
(int)(score * level * PRE_PENALTY));
score = score * PRE_PENALTY;
}
savescore(level);
 
showscores(level);
printf("\nHit 's' to new game, 'q' to quit.\n");
*/
tetris_menu_draw(*level);
while (1) {
int i = getchar();
i = getchar();
switch(i) {
case 'p':
showpreview = !showpreview;
moveto(9, 21);
moveto(9,21);
if (showpreview)
printf("on ");
else
printf("off");
break;
case 'h':
loadscores();
showscores(firstgame);
tetris_menu_draw(*level);
break;
221,103 → 235,112
case '3':
case '4':
case '5':
case '6':
case '6':
case '7':
case '8':
case '9':
*level = i - '0';
moveto(8, 18);
moveto(8,18);
printf("%d", *level);
break;
}
}
}
 
int main(int argc, char *argv[])
int
main(int argc, char *argv[])
{
int pos;
int c;
const char *keys;
int pos, c;
char *keys;
int level = 2;
char key_write[6][10];
int i;
int j;
int ch;
int i, j;
 
keys = "jkl pq";
 
// gid = getgid();
// egid = getegid();
// setegid(gid);
 
classic = 0;
showpreview = 1;
 
/* while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */
/* switch(ch) { */
/* case 'c': */
/* /\* */
/* * this means: */
/* * - rotate the other way; */
/* * - no reverse video. */
/* *\/ */
/* classic = 1; */
/* break; */
/* case 'k': */
/* if (str_size(keys = optarg) != 6) */
/* usage(); */
/* break; */
/* case 'l': */
/* level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */
/* &errstr); */
/* if (errstr) */
/* errx(1, "level must be from %d to %d", */
/* MINLEVEL, MAXLEVEL); */
/* break; */
/* case 'p': */
/* showpreview = 1; */
/* break; */
/* case 's': */
/* showscores(0); */
/* exit(0); */
/* default: */
/* usage(); */
/* } */
 
/* argc -= optind; */
/* argv += optind; */
 
/* if (argc) */
/* usage(); */
 
while ((ch = getopt(argc, argv, "ck:ps")) != -1)
switch(ch) {
case 'c':
/*
* this means:
* - rotate the other way
* - no reverse video
*/
classic = 1;
break;
case 'k':
if (str_size(keys = optarg) != 6)
usage();
break;
case 'p':
showpreview = 1;
break;
case 's':
showscores(0);
exit(0);
default:
usage();
}
argc -= optind;
argv += optind;
if (argc)
usage();
 
for (i = 0; i <= 5; i++) {
for (j = i + 1; j <= 5; j++) {
for (j = i+1; j <= 5; j++) {
if (keys[i] == keys[j])
errx(1, "duplicate command keys specified.");
}
if (keys[i] == ' ')
str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
str_cpy(key_write[i], sizeof key_write[i], "<space>");
else {
key_write[i][0] = keys[i];
key_write[i][1] = '\0';
}
}
snprintf(key_msg, sizeof(key_msg),
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
key_write[0], key_write[1], key_write[2], key_write[3],
key_write[4], key_write[5]);
 
snprintf(key_msg, sizeof key_msg,
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
key_write[0], key_write[1], key_write[2], key_write[3],
key_write[4], key_write[5]);
 
scr_init();
if (loadscores() != EOK)
initscores();
 
initscores();
while (tetris_menu(&level)) {
fallrate = 1000000 / level;
scr_clear();
setup_board();
srandomdev();
scr_set();
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
nextshape = randshape();
curshape = randshape();
scr_msg(key_msg, 1);
while (1) {
for (;;) {
place(curshape, pos, 1);
scr_update();
place(curshape, pos, 0);
330,7 → 353,7
pos += B_COLS;
continue;
}
/*
* Put up the current shape `permanently',
* bump score, and elide any full rows.
338,7 → 361,7
place(curshape, pos, 1);
score++;
elide();
/*
* Choose a new shape. If it does not fit,
* the game is over.
345,14 → 368,12
*/
curshape = nextshape;
nextshape = randshape();
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
if (!fits_in(curshape, pos))
break;
continue;
}
/*
* Handle command keys.
*/
360,11 → 381,10
/* quit */
break;
}
if (c == keys[4]) {
static char msg[] =
"paused - press RETURN to continue";
place(curshape, pos, 1);
do {
scr_update();
371,14 → 391,12
scr_msg(key_msg, 0);
scr_msg(msg, 1);
(void) fflush(stdout);
} while (rwait((struct timeval *) NULL) == -1);
} while (rwait((struct timeval *)NULL) == -1);
scr_msg(msg, 0);
scr_msg(key_msg, 1);
place(curshape, pos, 0);
continue;
}
if (c == keys[0]) {
/* move left */
if (fits_in(curshape, pos - 1))
385,17 → 403,15
pos--;
continue;
}
if (c == keys[1]) {
/* turn */
const struct shape *new =
&shapes[classic ? curshape->rotc : curshape->rot];
const struct shape *new = &shapes[
classic? curshape->rotc : curshape->rot];
if (fits_in(new, pos))
curshape = new;
continue;
}
if (c == keys[2]) {
/* move right */
if (fits_in(curshape, pos + 1))
402,7 → 418,6
pos++;
continue;
}
if (c == keys[3]) {
/* move to bottom */
while (fits_in(curshape, pos + B_COLS)) {
411,7 → 426,6
}
continue;
}
if (c == '\f') {
scr_clear();
scr_msg(key_msg, 1);
419,24 → 433,37
}
scr_clear();
loadscores();
insertscore(score, level);
savescores();
score = 0;
score=0;
}
scr_clear();
printf("\nGame over.\n");
printf("\n\n\n\t\tGame over.\n");
/*
while ((i = getchar()) != '\n')
if (i == EOF)
break
*/
scr_end();
 
return 0;
}
 
void usage(void)
/* void */
/* onintr(int signo) */
/* { */
/* scr_clear(); /\* XXX signal race *\/ */
/* scr_end(); /\* XXX signal race *\/ */
/* _exit(0); */
/* } */
 
void
usage(void)
{
fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");
(void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n");
exit(1);
}
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/screen.h
36,37 → 36,36
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
 
/*
* putpad() is for padded strings with count = 1.
* putpad() is for padded strings with count=1.
*/
#define putpad(s) tputs(s, 1, put)
#define putpad(s) tputs(s, 1, put)
 
#include <sys/types.h>
#include <async.h>
 
typedef struct {
ipcarg_t ws_row;
ipcarg_t ws_col;
int ws_row;
int ws_col;
} winsize_t;
 
extern winsize_t winsize;
 
extern void moveto(int r, int c);
extern void clear_screen(void);
void moveto(int r, int c);
void clear_screen(void);
 
/* just calls putchar; for tputs */
extern int put(int);
extern void scr_clear(void);
extern void scr_end(void);
extern void scr_init(void);
extern void scr_msg(char *, int);
extern void scr_set(void);
extern void scr_update(void);
int put(int); /* just calls putchar; for tputs */
void scr_clear(void);
void scr_end(void);
void scr_init(void);
void scr_msg(char *, int);
void scr_set(void);
void scr_update(void);
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/tetris.h
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
55,60 → 55,57
* worrying about addressing problems.
*/
 
/* The board */
#define B_COLS 12
#define B_ROWS 23
#define B_SIZE (B_ROWS * B_COLS)
/* the board */
#define B_COLS 12
#define B_ROWS 23
#define B_SIZE (B_ROWS * B_COLS)
 
typedef uint32_t cell;
typedef unsigned char cell;
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
 
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
/* the displayed area (rows) */
#define D_FIRST 1
#define D_LAST 22
 
/* The displayed area (rows) */
#define D_FIRST 1
#define D_LAST 22
/* the active area (rows) */
#define A_FIRST 1
#define A_LAST 21
 
/* The active area (rows) */
#define A_FIRST 1
#define A_LAST 21
 
/*
* Minimum display size.
*/
#define MINROWS 23
#define MINCOLS 40
#define MINROWS 23
#define MINCOLS 40
 
/* Current screen size */
extern int Rows;
extern int Cols;
extern int Rows, Cols; /* current screen size */
 
/*
* Translations from board coordinates to display coordinates.
* As with board coordinates, display coordiates are zero origin.
*/
#define RTOD(x) ((x) - 1)
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1))
#define RTOD(x) ((x) - 1)
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1))
 
/*
* A `shape' is the fundamental thing that makes up the game. There
* are 7 basic shapes, each consisting of four `blots':
*
* X.X X.X X.X
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X
* X X X
* X.X X.X X.X
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X
* X X X
*
* 0 1 2 3 4 5 6
* 0 1 2 3 4 5 6
*
* Except for 3 and 6, the center of each shape is one of the blots.
* This blot is designated (0, 0). The other three blots can then be
* This blot is designated (0,0). The other three blots can then be
* described as offsets from the center. Shape 3 is the same under
* rotation, so its center is effectively irrelevant; it has been chosen
* so that it `sticks out' upward and leftward. Except for shape 6,
* all the blots are contained in a box going from (-1, -1) to (+1, +1);
* all the blots are contained in a box going from (-1,-1) to (+1,+1);
* shape 6's center `wobbles' as it rotates, so that while it `sticks out'
* rightward, its rotation---a vertical line---`sticks out' downward.
* The containment box has to include the offset (2, 0), making the overall
* containment box range from offset (-1, -1) to (+2, +1). (This is why
* The containment box has to include the offset (2,0), making the overall
* containment box range from offset (-1,-1) to (+2,+1). (This is why
* there is only one row above, but two rows below, the display area.)
*
* The game works by choosing one of these shapes at random and putting
119,7 → 116,7
* At this time, any completely filled rows are elided, and blots above
* these rows move down to make more room. A new random shape is again
* introduced at the top of the board, and the whole process repeats.
* The game ends when the new shape will not fit at (1, 5).
* The game ends when the new shape will not fit at (1,5).
*
* While the shapes are falling, the user can rotate them counterclockwise
* 90 degrees (in addition to moving them left or right), provided that the
131,10 → 128,9
* rotated forms.
*/
struct shape {
int rot; /* index of rotated version of this shape */
int rotc; /* -- " -- in classic version */
int off[3]; /* offsets to other blots if center is at (0,0) */
uint32_t color;
int rot; /* index of rotated version of this shape */
int rotc; /* -- " -- in classic version */
int off[3]; /* offsets to other blots if center is at (0,0) */
};
 
extern const struct shape shapes[];
152,16 → 148,15
* The value eventually reaches a limit, and things stop going faster,
* but by then the game is utterly impossible.
*/
extern long fallrate; /* less than 1 million; smaller => faster */
extern long fallrate; /* less than 1 million; smaller => faster */
#define faster() (fallrate -= fallrate / 3000)
 
#define faster() (fallrate -= fallrate / 3000)
 
/*
* Game level must be between 1 and 9. This controls the initial fall rate
* and affects scoring.
*/
#define MINLEVEL 1
#define MAXLEVEL 9
#define MINLEVEL 1
#define MAXLEVEL 9
 
/*
* Scoring is as follows:
175,17 → 170,19
*
* If previewing has been turned on, the score is multiplied by PRE_PENALTY.
*/
#define PRE_PENALTY 0.75
#define PRE_PENALTY 0.75
 
extern int score; /* The obvious thing */
extern int score; /* the obvious thing */
//extern gid_t gid, egid;
 
extern char key_msg[100];
extern int showpreview;
extern int classic;
extern char key_msg[100];
extern int showpreview;
extern int classic;
 
extern int fits_in(const struct shape *, int);
extern void place(const struct shape *, int, int);
extern void stop(char *);
int fits_in(const struct shape *, int);
void place(const struct shape *, int, int);
void stop(char *);
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/shapes.c
36,7 → 36,7
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
50,35 → 50,35
#include <unistd.h>
#include "tetris.h"
 
#define TL (-B_COLS - 1) /* top left */
#define TC (-B_COLS) /* top center */
#define TR (-B_COLS + 1) /* top right */
#define ML -1 /* middle left */
#define MR 1 /* middle right */
#define BL (B_COLS - 1) /* bottom left */
#define BC B_COLS /* bottom center */
#define BR (B_COLS + 1) /* bottom right */
#define TL -B_COLS-1 /* top left */
#define TC -B_COLS /* top center */
#define TR -B_COLS+1 /* top right */
#define ML -1 /* middle left */
#define MR 1 /* middle right */
#define BL B_COLS-1 /* bottom left */
#define BC B_COLS /* bottom center */
#define BR B_COLS+1 /* bottom right */
 
const struct shape shapes[] = {
/* 0 */ { 7, 7, { TL, TC, MR }, 0xff042d},
/* 1 */ { 8, 8, { TC, TR, ML }, 0xff9304},
/* 2 */ { 9, 11, { ML, MR, BC }, 0xbeff04},
/* 3 */ { 3, 3, { TL, TC, ML }, 0x63ff04},
/* 4 */ { 12, 14, { ML, BL, MR }, 0xce04ff},
/* 5 */ { 15, 17, { ML, BR, MR }, 0xff04cf},
/* 6 */ { 18, 18, { ML, MR, 2 }, 0x7604ff}, /* sticks out */
/* 7 */ { 0, 0, { TC, ML, BL }, 0xff042d},
/* 8 */ { 1, 1, { TC, MR, BR }, 0xff9304},
/* 9 */ { 10, 2, { TC, MR, BC }, 0xbeff04},
/* 10 */ { 11, 9, { TC, ML, MR }, 0xbeff04},
/* 11 */ { 2, 10, { TC, ML, BC }, 0xbeff04},
/* 12 */ { 13, 4, { TC, BC, BR }, 0xce04ff},
/* 13 */ { 14, 12, { TR, ML, MR }, 0xce04ff},
/* 14 */ { 4, 13, { TL, TC, BC }, 0xce04ff},
/* 15 */ { 16, 5, { TR, TC, BC }, 0xff04cf},
/* 16 */ { 17, 15, { TL, MR, ML }, 0xff04cf},
/* 17 */ { 5, 16, { TC, BC, BL }, 0xff04cf},
/* 18 */ { 6, 6, { TC, BC, 2 * B_COLS }, 0x7604ff} /* sticks out */
/* 0*/ { 7, 7, { TL, TC, MR } },
/* 1*/ { 8, 8, { TC, TR, ML } },
/* 2*/ { 9, 11, { ML, MR, BC } },
/* 3*/ { 3, 3, { TL, TC, ML } },
/* 4*/ { 12, 14, { ML, BL, MR } },
/* 5*/ { 15, 17, { ML, BR, MR } },
/* 6*/ { 18, 18, { ML, MR, 2 } }, /* sticks out */
/* 7*/ { 0, 0, { TC, ML, BL } },
/* 8*/ { 1, 1, { TC, MR, BR } },
/* 9*/ { 10, 2, { TC, MR, BC } },
/*10*/ { 11, 9, { TC, ML, MR } },
/*11*/ { 2, 10, { TC, ML, BC } },
/*12*/ { 13, 4, { TC, BC, BR } },
/*13*/ { 14, 12, { TR, ML, MR } },
/*14*/ { 4, 13, { TL, TC, BC } },
/*15*/ { 16, 5, { TR, TC, BC } },
/*16*/ { 17, 15, { TL, MR, ML } },
/*17*/ { 5, 16, { TC, BC, BL } },
/*18*/ { 6, 6, { TC, BC, 2*B_COLS } }/* sticks out */
};
 
/*
85,14 → 85,14
* Return true iff the given shape fits in the given position,
* taking the current board into account.
*/
int fits_in(const struct shape *shape, int pos)
int
fits_in(const struct shape *shape, int pos)
{
const int *o = shape->off;
if ((board[pos]) || (board[pos + *o++]) || (board[pos + *o++]) ||
(board[pos + *o]))
int *o = shape->off;
 
if (board[pos] || board[pos + *o++] || board[pos + *o++] ||
board[pos + *o])
return 0;
return 1;
}
 
100,15 → 100,17
* Write the given shape into the current board, turning it on
* if `onoff' is 1, and off if `onoff' is 0.
*/
void place(const struct shape *shape, int pos, int onoff)
void
place(const struct shape *shape, int pos, int onoff)
{
const int *o = shape->off;
board[pos] = onoff ? shape->color : 0x000000;
board[pos + *o++] = onoff ? shape->color : 0x000000;
board[pos + *o++] = onoff ? shape->color : 0x000000;
board[pos + *o] = onoff ? shape->color : 0x000000;
int *o = shape->off;
 
board[pos] = onoff;
board[pos + *o++] = onoff;
board[pos + *o++] = onoff;
board[pos + *o] = onoff;
}
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/input.h
36,14 → 36,15
*/
 
/** @addtogroup tetris
* @{
* @{
*/
/** @file
*/
 
extern int rwait(struct timeval *);
extern int tgetchar(void);
extern void tsleep(void);
int rwait(struct timeval *);
int tgetchar(void);
void tsleep(void);
 
/** @}
*/
 
/branches/dynload/uspace/app/tetris/pathnames.h
0,0 → 1,49
/* $OpenBSD: pathnames.h,v 1.3 2003/06/03 03:01:41 millert Exp $ */
/* $NetBSD: pathnames.h,v 1.2 1995/04/22 07:42:37 cgd Exp $ */
 
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek and Darren F. Provine.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*
* @(#)pathnames.h 8.1 (Berkeley) 5/31/93
*/
 
/** @addtogroup tetris
* @{
*/
/** @file
*/
 
#define _PATH_SCOREFILE "/var/games/tetris.scores"
 
 
/** @}
*/
 
/branches/dynload/uspace/app/klog/Makefile
63,7 → 63,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/app/klog/klog.c
40,34 → 40,41
#include <ipc/services.h>
#include <as.h>
#include <sysinfo.h>
#include <io/stream.h>
#include <console.h>
#include <event.h>
#include <errno.h>
#include <io/klog.h>
 
#define NAME "klog"
#define NAME "klog"
 
/* Pointer to klog area */
static wchar_t *klog;
static size_t klog_length;
static count_t klog_length;
 
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
{
size_t klog_start = (size_t) IPC_GET_ARG1(*call);
size_t klog_len = (size_t) IPC_GET_ARG2(*call);
size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
size_t i;
async_serialize_start();
count_t klog_start = (count_t) IPC_GET_ARG1(*call);
count_t klog_len = (count_t) IPC_GET_ARG2(*call);
count_t klog_stored = (count_t) IPC_GET_ARG3(*call);
count_t i;
for (i = klog_len - klog_stored; i < klog_len; i++)
putchar(klog[(klog_start + i) % klog_length]);
async_serialize_end();
}
 
int main(int argc, char *argv[])
{
size_t klog_pages = sysinfo_value("klog.pages");
console_wait();
count_t klog_pages = sysinfo_value("klog.pages");
size_t klog_size = klog_pages * PAGE_SIZE;
klog_length = klog_size / sizeof(wchar_t);
klog = (wchar_t *) as_get_mappable_page(klog_size);
klog = (wchar_t *) as_get_mappable_page(klog_pages);
if (klog == NULL) {
printf(NAME ": Error allocating memory area\n");
return -1;
/branches/dynload/uspace/app/init/init.c
41,87 → 41,41
#include <bool.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <task.h>
#include <malloc.h>
#include <macros.h>
#include <console.h>
#include <string.h>
#include <devmap.h>
#include <config.h>
#include "init.h"
#include "version.h"
 
static void info_print(void)
static bool mount_fs(const char *fstype)
{
printf(NAME ": HelenOS init\n");
}
 
static bool mount_root(const char *fstype)
{
int rc = -1;
char *opts = "";
const char *root_dev = "initrd";
if (str_cmp(fstype, "tmpfs") == 0)
opts = "restore";
int rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted, %s at %s\n",
fstype, root_dev);
break;
case EBUSY:
printf(NAME ": Root filesystem already mounted\n");
return false;
case ELIMIT:
printf(NAME ": Unable to mount root filesystem\n");
return false;
case ENOENT:
printf(NAME ": Unknown filesystem type (%s)\n", fstype);
return false;
default:
printf(NAME ": Error mounting root filesystem (%d)\n", rc);
return false;
}
return true;
}
 
static bool mount_devfs(void)
{
char null[MAX_DEVICE_NAME];
int null_id = devmap_null_create();
if (null_id == -1) {
printf(NAME ": Unable to create null device\n");
return false;
while (rc < 0) {
rc = mount(fstype, "/", "initrd", opts, IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted\n");
break;
case EBUSY:
printf(NAME ": Root filesystem already mounted\n");
break;
case ELIMIT:
printf(NAME ": Unable to mount root filesystem\n");
return false;
case ENOENT:
printf(NAME ": Unknown filesystem type (%s)\n", fstype);
return false;
}
}
snprintf(null, MAX_DEVICE_NAME, "null%d", null_id);
int rc = mount("devfs", "/dev", null, "", IPC_FLAG_BLOCKING);
switch (rc) {
case EOK:
printf(NAME ": Device filesystem mounted\n");
break;
case EBUSY:
printf(NAME ": Device filesystem already mounted\n");
devmap_null_destroy(null_id);
return false;
case ELIMIT:
printf(NAME ": Unable to mount device filesystem\n");
devmap_null_destroy(null_id);
return false;
case ENOENT:
printf(NAME ": Unknown filesystem type (devfs)\n");
devmap_null_destroy(null_id);
return false;
default:
printf(NAME ": Error mounting device filesystem (%d)\n", rc);
devmap_null_destroy(null_id);
return false;
}
return true;
}
 
128,11 → 82,7
static void spawn(char *fname)
{
char *argv[2];
struct stat s;
if (stat(fname, &s) == ENOENT)
return;
printf(NAME ": Spawning %s\n", fname);
argv[0] = fname;
142,127 → 92,28
printf(NAME ": Error spawning %s\n", fname);
}
 
static void srv_start(char *fname)
{
char *argv[2];
task_id_t id;
task_exit_t texit;
int rc, retval;
struct stat s;
if (stat(fname, &s) == ENOENT)
return;
printf(NAME ": Starting %s\n", fname);
argv[0] = fname;
argv[1] = NULL;
id = task_spawn(fname, argv);
if (!id) {
printf(NAME ": Error spawning %s\n", fname);
return;
}
 
rc = task_wait(id, &texit, &retval);
if (rc != EOK) {
printf(NAME ": Error waiting for %s\n", fname);
return;
}
 
if (texit != TASK_EXIT_NORMAL || retval != 0) {
printf(NAME ": Server %s failed to start (returned %d)\n",
fname, retval);
}
}
 
static void getvc(char *dev, char *app)
{
char *argv[4];
char vc[MAX_DEVICE_NAME];
int rc;
snprintf(vc, MAX_DEVICE_NAME, "/dev/%s", dev);
printf(NAME ": Spawning getvc on %s\n", vc);
dev_handle_t handle;
rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
if (rc == EOK) {
argv[0] = "/app/getvc";
argv[1] = vc;
argv[2] = app;
argv[3] = NULL;
if (!task_spawn("/app/getvc", argv))
printf(NAME ": Error spawning getvc on %s\n", vc);
} else {
printf(NAME ": Error waiting on %s\n", vc);
}
}
 
static void mount_data(void)
{
int rc;
 
printf("Trying to mount disk0 on /data... ");
fflush(stdout);
 
rc = mount("fat", "/data", "disk0", "wtcache", 0);
if (rc == EOK)
printf("OK\n");
else
printf("Failed\n");
}
 
int main(int argc, char *argv[])
{
info_print();
if (!mount_root(STRING(RDFMT))) {
if (!mount_fs(STRING(RDFMT))) {
printf(NAME ": Exiting\n");
return -1;
}
spawn("/srv/devfs");
if (!mount_devfs()) {
printf(NAME ": Exiting\n");
return -2;
}
// FIXME: spawn("/srv/pci");
spawn("/srv/fb");
spawn("/srv/kbd");
spawn("/srv/console");
spawn("/srv/fhc");
spawn("/srv/obio");
 
/*
* Start these synchronously so that mount_data() can be
* non-blocking.
*/
#ifdef CONFIG_START_BD
srv_start("/srv/ata_bd");
srv_start("/srv/gxe_bd");
#else
(void) srv_start;
#endif
 
#ifdef CONFIG_MOUNT_DATA
mount_data();
#else
(void) mount_data;
#endif
 
getvc("vc0", "/app/bdsh");
getvc("vc1", "/app/bdsh");
getvc("vc2", "/app/bdsh");
getvc("vc3", "/app/bdsh");
getvc("vc4", "/app/bdsh");
getvc("vc5", "/app/bdsh");
getvc("vc6", "/app/klog");
console_wait();
version_print();
spawn("/app/klog");
spawn("/app/bdsh");
return 0;
}
 
/branches/dynload/uspace/app/init/version.c
0,0 → 1,69
/*
* 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 init
* @{
*/
/**
* @file
*/
 
#include <unistd.h>
#include <stdio.h>
#include <macros.h>
#include "init.h"
#include "version.h"
 
char *release = STRING(RELEASE);
 
#ifdef REVISION
char *revision = ", revision " STRING(REVISION);
#else
char *revision = "";
#endif
 
#ifdef TIMESTAMP
char *timestamp = "\nBuilt on " STRING(TIMESTAMP);
#else
char *timestamp = "";
#endif
 
void info_print(void)
{
printf(NAME ": HelenOS init\n");
}
 
/** Print version information. */
void version_print(void)
{
printf("HelenOS init\nRelease %s%s%s\n", release, revision, timestamp);
printf("Copyright (c) 2001-2009 HelenOS project\n");
}
 
/** @}
*/
/branches/dynload/uspace/app/init/Makefile
26,6 → 26,8
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
 
## Setup toolchain
#
 
34,8 → 36,10
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../..
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=$(RELEASE)
 
## Sources
#
42,7 → 46,8
 
OUTPUT = init
SOURCES = \
init.c
init.c \
version.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
64,7 → 69,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/app/init/init.h
28,7 → 28,7
 
/** @addtogroup init
* @{
*/
*/
/**
* @file
*/
36,11 → 36,10
#ifndef __INIT_H__
#define __INIT_H__
 
#define NAME "init"
#define NAME "init"
 
#define MAX_DEVICE_NAME 32
 
#endif
 
/** @}
*/
 
/branches/dynload/uspace/app/init/version.h
0,0 → 1,46
/*
* Copyright (c) 2006 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 init
* @{
*/
/**
* @file
*/
 
#ifndef __VERSION_H__
#define __VERSION_H__
 
extern void info_print(void);
extern void version_print(void);
 
#endif
 
/** @}
*/
 
/branches/dynload/uspace/lib/libfs/libfs.c
1,5 → 1,5
/*
* Copyright (c) 2009 Jakub Jermar
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
42,8 → 42,6
#include <as.h>
#include <assert.h>
#include <dirent.h>
#include <mem.h>
#include <sys/stat.h>
 
/** Register file system server.
*
70,7 → 68,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_IN_REGISTER, &answer);
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer);
 
/*
* Send our VFS info structure to VFS.
105,7 → 103,7
}
/*
* Pick up the answer for the request to the VFS_IN_REQUEST call.
* Pick up the answer for the request to the VFS_REQUEST call.
*/
async_wait_for(req, NULL);
reg->fs_handle = (int) IPC_GET_ARG1(answer);
124,106 → 122,23
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_OUT_LOOKUP request.
* @param request VFS_OUT_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_LOOKUP request.
* @param request VFS_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 first = IPC_GET_ARG1(*request);
unsigned next = 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 */
237,14 → 152,6
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 */
267,21 → 174,6
 
/* 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) {
429,62 → 321,5
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) 2009 Jakub Jermar
* Copyright (c) 2007 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
26,32 → 26,23
* 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 <ipc/vfs.h>
#include "../../srv/vfs/vfs.h"
#include <stdint.h>
#include <ipc/ipc.h>
#include <async.h>
#include <devmap.h>
 
typedef struct {
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. */
void *data; /**< Data of the file system implementation. */
} fs_node_t;
 
typedef struct {
67,28 → 58,23
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/libc/include/devmap.h
File deleted
/branches/dynload/uspace/lib/libc/include/fibril_sync.h
File deleted
/branches/dynload/uspace/lib/libc/include/adt/fifo.h
File deleted
/branches/dynload/uspace/lib/libc/include/adt/gcdlcm.h
File deleted
/branches/dynload/uspace/lib/libc/include/adt/hash_table.h
File deleted
/branches/dynload/uspace/lib/libc/include/adt/list.h
File deleted
/branches/dynload/uspace/lib/libc/include/string.h
39,7 → 39,8
#include <sys/types.h>
#include <bool.h>
 
#define U_SPECIAL '?'
#define U_SPECIAL '?'
#define U_BOM 0xfeff
 
/** No size limit constant */
#define STR_NO_LIMIT ((size_t) -1)
53,20 → 54,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, size_t max_len);
extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
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_length(const char *str);
extern size_t wstr_length(const wchar_t *wstr);
extern count_t str_length(const char *str);
extern count_t wstr_length(const wchar_t *wstr);
 
extern size_t str_nlength(const char *str, size_t size);
extern size_t wstr_nlength(const wchar_t *str, size_t size);
extern count_t str_nlength(const char *str, size_t size);
extern count_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, size_t max_len);
extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
 
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
74,11 → 75,11
 
extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
 
extern char *str_chr(const char *str, wchar_t ch);
extern char *str_rchr(const char *str, wchar_t ch);
extern const char *str_chr(const char *str, wchar_t ch);
extern const char *str_rchr(const char *str, wchar_t ch);
 
extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
extern bool wstr_remove(wchar_t *str, size_t pos);
extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
extern bool wstr_remove(wchar_t *str, count_t pos);
 
extern char *str_dup(const char *);
 
/branches/dynload/uspace/lib/libc/include/io/keycode.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/color.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/console.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/klog.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/style.h
File deleted
/branches/dynload/uspace/lib/libc/include/io/stream.h
0,0 → 1,49
/*
* 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 <libarch/types.h>
 
#define EMFILE -17
 
extern ssize_t read_stdin(void *, size_t);
extern int klog_puts(const char *);
extern void klog_update(void);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/io/printf_core.h
56,3 → 56,5
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/io/io.h
0,0 → 1,50
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_IO_H_
#define LIBC_IO_H_
 
#include <sys/types.h>
 
int putnchars(const char * buf, size_t count);
int putstr(const char * str);
int putchar(int c);
int getchar(void);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/console.h
0,0 → 1,65
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_H_
#define LIBC_CONSOLE_H_
 
#include <console/style.h>
#include <console/color.h>
#include <sys/types.h>
#include <bool.h>
 
extern int console_open(bool);
extern void console_close(void);
extern void console_wait(void);
 
extern void console_clear(void);
extern void console_goto(int, int);
extern void console_putchar(wchar_t);
extern ssize_t console_write(const char *, size_t);
extern void console_putstr(const char *);
extern void console_flush(void);
 
extern int console_get_size(int *, int *);
extern void console_set_style(int);
extern void console_set_color(int, int, int);
extern void console_set_rgb_color(int, int);
extern void console_cursor_visibility(int);
 
extern void console_kcon_enable(void);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/vfs/vfs.h
36,36 → 36,12
#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 *,
unsigned int);
const unsigned int flags);
 
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,21 → 44,17
typedef ipc_callid_t aid_t;
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
 
extern atomic_t async_futex;
static inline void async_manager(void)
{
fibril_switch(FIBRIL_TO_MANAGER);
}
 
extern int __async_init(void);
extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
 
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
67,19 → 63,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);
90,11 → 86,12
extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
suseconds_t timeout);
 
extern fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
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 *));
extern void async_usleep(suseconds_t timeout);
extern void async_create_manager(void);
extern void async_destroy_manager(void);
void async_usleep(suseconds_t timeout);
void async_create_manager(void);
void async_destroy_manager(void);
int _async_init(void);
 
extern void async_set_client_connection(async_client_conn_t conn);
extern void async_set_interrupt_received(async_client_conn_t conn);
101,22 → 98,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
125,90 → 122,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), \
218,14 → 215,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), \
256,6 → 253,8
fibril_dec_sercount();
}
 
extern atomic_t async_futex;
 
#endif
 
/** @}
/branches/dynload/uspace/lib/libc/include/stdio.h
37,118 → 37,78
 
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <adt/list.h>
 
#define EOF (-1)
#define EOF (-1)
 
/** Default size for stream I/O buffers */
#define BUFSIZ 4096
#include <string.h>
#include <io/stream.h>
 
#define DEBUG(fmt, ...) \
{ \
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)); \
}
{ \
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)); \
}
 
#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;
extern FILE *stdout;
extern FILE *stderr;
extern FILE *stdin, *stdout, *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 asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
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 vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
/* File stream functions */
extern int rename(const char *, const char *);
 
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 void setvbuf(FILE *, void *, int, size_t);
extern int fgetc(FILE *);
extern int fputc(int, FILE *);
extern int fputs(const char *, FILE *);
 
/* Misc file functions */
extern int rename(const char *, const char *);
extern int fprintf(FILE *, const char *, ...);
extern int vfprintf(FILE *, const char *, va_list);
 
#define getc fgetc
#define putc fputc
 
extern int fseek(FILE *, long, int);
 
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/unistd.h
39,32 → 39,29
#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/kbd/kbd.h
0,0 → 1,65
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_KBD_H_
#define LIBC_KBD_H_
 
#include <sys/types.h>
 
typedef enum kbd_ev_type {
KE_PRESS,
KE_RELEASE
} kbd_ev_type_t;
 
/** Keyboard event structure. */
typedef struct {
/** Press or release event. */
kbd_ev_type_t type;
 
/** Keycode of the key that was pressed or released. */
unsigned int key;
 
/** Bitmask of modifiers held. */
unsigned int mods;
 
/** The character that was generated or '\0' for none. */
wchar_t c;
} kbd_event_t;
 
extern int kbd_get_event(kbd_event_t *);
 
#endif
/** @}
*/
/branches/dynload/uspace/lib/libc/include/kbd/keycode.h
0,0 → 1,220
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_KBD_KEYCODE_H_
#define LIBC_KBD_KEYCODE_H_
 
/** Keycode definitions.
*
* A keycode identifies a key by its position on the keyboard, rather
* than by its label. For human readability, key positions are noted
* with the key label on a keyboard with US layout. This label has
* nothing to do with the character, that the key produces
* -- this is determined by the keymap.
*
* The keyboard model reflects a standard PC keyboard layout.
* Non-standard keyboards need to be mapped to this model in some
* logical way. Scancodes are mapped to keycodes with a scanmap.
*
* For easier mapping to the model and to emphasize the nature of keycodes,
* they really are organized here by position, rather than by label.
*/
enum keycode {
 
/* Main block row 1 */
 
KC_BACKTICK = 1,
 
KC_1,
KC_2,
KC_3,
KC_4,
KC_5,
KC_6,
KC_7,
KC_8,
KC_9,
KC_0,
 
KC_MINUS,
KC_EQUALS,
KC_BACKSPACE,
 
/* Main block row 2 */
 
KC_TAB,
 
KC_Q,
KC_W,
KC_E,
KC_R,
KC_T,
KC_Y,
KC_U,
KC_I,
KC_O,
KC_P,
 
KC_LBRACKET,
KC_RBRACKET,
 
/* Main block row 3 */
 
KC_CAPS_LOCK,
KC_A,
KC_S,
KC_D,
KC_F,
KC_G,
KC_H,
KC_J,
KC_K,
KC_L,
 
KC_SEMICOLON,
KC_QUOTE,
KC_BACKSLASH,
 
KC_ENTER,
 
/* Main block row 4 */
 
KC_LSHIFT,
 
KC_Z,
KC_X,
KC_C,
KC_V,
KC_B,
KC_N,
KC_M,
 
KC_COMMA,
KC_PERIOD,
KC_SLASH,
 
KC_RSHIFT,
 
/* Main block row 5 */
 
KC_LCTRL,
KC_LALT,
KC_SPACE,
KC_RALT,
KC_RCTRL,
 
/* Function keys block */
 
KC_ESCAPE,
 
KC_F1,
KC_F2,
KC_F3,
KC_F4,
KC_F5,
KC_F6,
KC_F7,
KC_F8,
KC_F9,
KC_F10,
KC_F11,
KC_F12,
 
KC_PRTSCR,
KC_SCROLL_LOCK,
KC_PAUSE,
 
/* Cursor keys block */
 
KC_INSERT,
KC_HOME,
KC_PAGE_UP,
 
KC_DELETE,
KC_END,
KC_PAGE_DOWN,
 
KC_UP,
KC_LEFT,
KC_DOWN,
KC_RIGHT,
 
/* Numeric block */
 
KC_NUM_LOCK,
KC_NSLASH,
KC_NTIMES,
KC_NMINUS,
 
KC_NPLUS,
KC_NENTER,
 
KC_N7,
KC_N8,
KC_N9,
 
KC_N4,
KC_N5,
KC_N6,
 
KC_N1,
KC_N2,
KC_N3,
 
KC_N0,
KC_NPERIOD
} keycode_t;
 
enum keymod {
KM_LSHIFT = 0x001,
KM_RSHIFT = 0x002,
KM_LCTRL = 0x004,
KM_RCTRL = 0x008,
KM_LALT = 0x010,
KM_RALT = 0x020,
KM_CAPS_LOCK = 0x040,
KM_NUM_LOCK = 0x080,
KM_SCROLL_LOCK = 0x100,
 
KM_SHIFT = KM_LSHIFT | KM_RSHIFT,
KM_CTRL = KM_LCTRL | KM_RCTRL,
KM_ALT = KM_LALT | KM_RALT
} keymod_t;
 
#endif
/** @}
*/
/branches/dynload/uspace/lib/libc/include/ipc/vfs.h
File deleted
/branches/dynload/uspace/lib/libc/include/ipc/bd.h
File deleted
/branches/dynload/uspace/lib/libc/include/ipc/fb.h
41,7 → 41,6
FB_PUTCHAR = IPC_FIRST_USER_METHOD,
FB_CLEAR,
FB_GET_CSIZE,
FB_GET_COLOR_CAP,
FB_CURSOR_VISIBILITY,
FB_CURSOR_GOTO,
FB_SCROLL,
72,13 → 71,6
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/ipc/console.h
27,7 → 27,7
*/
 
/** @addtogroup libcipc
* @{
* @{
*/
/** @file
*/
36,14 → 36,15
#define LIBC_IPC_CONSOLE_H_
 
#include <ipc/ipc.h>
#include <ipc/vfs.h>
 
typedef enum {
CONSOLE_GET_SIZE = VFS_OUT_LAST,
CONSOLE_GET_COLOR_CAP,
CONSOLE_GET_EVENT,
CONSOLE_GETKEY = IPC_FIRST_USER_METHOD,
CONSOLE_PUTCHAR,
CONSOLE_WRITE,
CONSOLE_CLEAR,
CONSOLE_GOTO,
CONSOLE_CLEAR,
CONSOLE_GETSIZE,
CONSOLE_FLUSH,
CONSOLE_SET_STYLE,
CONSOLE_SET_COLOR,
CONSOLE_SET_RGB_COLOR,
52,6 → 53,6
} console_request_t;
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/ipc/ipc.h
30,26 → 30,21
* @{
*/
/** @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 *);
61,51 → 56,49
* 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), \
114,16 → 107,15
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), \
136,16 → 128,15
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), \
158,13 → 149,12
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), \
191,12 → 181,10
 
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 *);
 
/*
206,17 → 194,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);
258,6 → 246,8
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);
266,19 → 256,20
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 *);
293,6 → 284,8
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/loader.h
42,7 → 42,6
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/devmap.h
28,19 → 28,16
 
/** @addtogroup devmap
* @{
*/
*/
 
#ifndef DEVMAP_DEVMAP_H_
#define DEVMAP_DEVMAP_H_
 
#include <atomic.h>
#include <ipc/ipc.h>
#include <adt/list.h>
#include <libadt/list.h>
 
#define DEVMAP_NAME_MAXLEN 255
#define DEVMAP_NAME_MAXLEN 512
 
typedef ipcarg_t dev_handle_t;
 
typedef enum {
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
DEVMAP_DRIVER_UNREGISTER,
47,32 → 44,56
DEVMAP_DEVICE_REGISTER,
DEVMAP_DEVICE_UNREGISTER,
DEVMAP_DEVICE_GET_NAME,
DEVMAP_DEVICE_GET_HANDLE,
DEVMAP_DEVICE_NULL_CREATE,
DEVMAP_DEVICE_NULL_DESTROY,
DEVMAP_DEVICE_GET_COUNT,
DEVMAP_DEVICE_GET_DEVICES
DEVMAP_DEVICE_GET_HANDLE
} devmap_request_t;
 
/** Interface provided by devmap.
/** 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
*
*/
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
 
#endif
/branches/dynload/uspace/lib/libc/include/ipc/ns.h
35,15 → 35,6
#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/sys/stat.h
36,26 → 36,7
#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/include/task.h
39,18 → 39,10
 
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/loader/loader.h
37,7 → 37,6
#define LIBC_LOADER_H_
 
#include <task.h>
#include <vfs/vfs.h>
 
/** Abstraction of a loader connection */
typedef struct {
49,8 → 48,7
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_files(loader_t *, fdi_node_t *const[]);
extern int loader_set_args(loader_t *, char *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/loader/pcb.h
37,7 → 37,6
#define LIBC_PCB_H_
 
#include <sys/types.h>
#include <vfs/vfs.h>
 
typedef void (*entry_point_t)(void);
 
46,26 → 45,19
* 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/macros.h
35,25 → 35,15
#ifndef LIBC_MACROS_H_
#define LIBC_MACROS_H_
 
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
#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/console/color.h
0,0 → 1,55
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_COLOR_H_
#define LIBC_CONSOLE_COLOR_H_
 
enum console_color {
COLOR_BLACK = 0,
COLOR_BLUE = 1,
COLOR_GREEN = 2,
COLOR_CYAN = 3,
COLOR_RED = 4,
COLOR_MAGENTA = 5,
COLOR_YELLOW = 6,
COLOR_WHITE = 7,
 
CATTR_BRIGHT = 8,
CATTR_BLINK = 8
};
 
#endif
/** @}
*/
/branches/dynload/uspace/lib/libc/include/console/style.h
0,0 → 1,46
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_CONSOLE_STYLE_H_
#define LIBC_CONSOLE_STYLE_H_
 
enum console_style {
STYLE_NORMAL = 0,
STYLE_EMPHASIS = 1
};
 
#endif
/** @}
*/
/branches/dynload/uspace/lib/libc/include/errno.h
35,26 → 35,24
#ifndef LIBC_ERRNO_H_
#define LIBC_ERRNO_H_
 
#include <kernel/errno.h>
#include <fibril.h>
 
/* TODO: support threads/fibrils */
extern int _errno;
 
#define errno _errno
 
#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)
#include <kernel/errno.h>
 
#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/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/byteorder.h
35,47 → 35,48
#ifndef LIBC_BYTEORDER_H_
#define LIBC_BYTEORDER_H_
 
#include <libarch/byteorder.h>
#include <stdint.h>
 
#if !(defined(__BE__) ^ defined(__LE__))
#error The architecture must be either big-endian or little-endian.
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN))
#error The architecture must be either big-endian or little-endian.
#endif
 
#ifdef __BE__
#ifdef ARCH_IS_BIG_ENDIAN
 
#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 const char *optarg;
extern char *optarg;
extern int optind, opterr, optopt;
extern int optreset;
 
/branches/dynload/uspace/lib/libc/include/libadt/list.h
0,0 → 1,206
/*
* 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>
 
#ifndef true
# define true 1
#endif
#ifndef false
# define false 0
#endif
 
typedef struct link link_t;
 
/** Doubly linked list head and link type. */
struct link {
link_t *prev; /**< Pointer to the previous item in the list. */
link_t *next; /**< Pointer to the next item in the list. */
};
 
/** 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 ? true : false;
}
 
 
/** 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)
{
link_t *hlp;
 
part1->prev->next = part2;
part2->prev->next = part1;
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 *)(((char *)(link))-((char *)&(((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);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/include/libadt/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 <libadt/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/libadt/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/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/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,6 → 46,7
struct dirent res;
} DIR;
 
 
extern DIR *opendir(const char *);
extern struct dirent *readdir(DIR *);
extern void rewinddir(DIR *);
/branches/dynload/uspace/lib/libc/include/fibril.h
36,18 → 36,17
#define LIBC_FIBRIL_H_
 
#include <libarch/fibril.h>
#include <adt/list.h>
#include <libadt/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_WRITER 2
#define FIBRIL_SERIALIZED 1
 
typedef enum {
FIBRIL_PREEMPT,
72,10 → 71,7
};
typedef struct fibril fibril_t;
 
/** Fibril-local variable specifier */
#define fibril_local __thread
 
extern int context_save(context_t *c) __attribute__ ((returns_twice));
extern int context_save(context_t *c);
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/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 unsigned int fnzb32(uint32_t arg)
static inline int fnzb32(uint32_t arg)
{
unsigned int n = 0;
int n = 0;
 
if (arg >> 16) {
arg >>= 16;
n += 16;
74,22 → 74,19
return n;
}
 
static inline unsigned int fnzb64(uint64_t arg)
static inline int fnzb64(uint64_t arg)
{
unsigned int n = 0;
int n = 0;
 
if (arg >> 32) {
arg >>= 32;
n += 32;
}
return (n + fnzb32((uint32_t) arg));
return n + fnzb32((uint32_t) arg);
}
 
static inline unsigned int fnzb(size_t arg)
{
return fnzb64(arg);
}
#define fnzb(x) fnzb32(x)
 
#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,7 → 50,6
{
return random();
}
 
static inline void srand(unsigned int seed)
{
srandom(seed);
/branches/dynload/uspace/lib/libc/include/malloc.h
1,51 → 1,537
/*
* 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.
*/
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)
 
/** @addtogroup libc
* @{
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.
*/
/** @file
*/
void* dlpvalloc(size_t);
 
#ifndef LIBC_MALLOC_H_
#define LIBC_MALLOC_H_
/*
malloc_trim(size_t pad);
 
#include <sys/types.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.
 
extern void __heap_init(void);
extern uintptr_t get_max_heap_addr(void);
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 *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_trim returns 1 if it actually released any memory, else 0.
*/
int dlmalloc_trim(size_t);
 
/*
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/generic/devmap.c
File deleted
/branches/dynload/uspace/lib/libc/generic/fibril_sync.c
File deleted
/branches/dynload/uspace/lib/libc/generic/errno.c
File deleted
/branches/dynload/uspace/lib/libc/generic/malloc.c
File deleted
/branches/dynload/uspace/lib/libc/generic/adt/hash_table.c
File deleted
/branches/dynload/uspace/lib/libc/generic/adt/list.c
File deleted
/branches/dynload/uspace/lib/libc/generic/async.c
95,8 → 95,8
#include <async.h>
#include <fibril.h>
#include <stdio.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <libadt/hash_table.h>
#include <libadt/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 fibril_local connection_t *FIBRIL_connection;
static __thread 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,9 → 190,11
*/
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.
498,10 → 500,9
/* Answer all remaining messages with EHANGUP */
while (!list_empty(&FIBRIL_connection->msg_queue)) {
msg_t *msg;
msg_t *msg
= list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, link);
msg = list_get_instance(FIBRIL_connection->msg_queue.next,
msg_t, link);
list_remove(&msg->link);
ipc_answer_0(msg->callid, EHANGUP);
free(msg);
562,7 → 563,7
}
/* Add connection to the connection hash table */
unsigned long key = conn->in_phone_hash;
ipcarg_t key = conn->in_phone_hash;
futex_down(&async_futex);
hash_table_insert(&conn_hash_table, &key, &conn->link);
587,28 → 588,23
/* Unrouted call - do some default behaviour */
if ((callid & IPC_CALLID_NOTIFICATION)) {
process_notification(callid, call);
goto out;
return;
}
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);
goto out;
return;
}
/* Try to route the call through the connection hash table */
if (route_call(callid, call))
goto out;
return;
/* Unknown call from unknown phone - hang it up */
ipc_answer_0(callid, EHANGUP);
return;
out:
;
}
 
/** Fire all timeouts that expired. */
666,8 → 662,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);
684,8 → 680,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();
738,7 → 734,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)) {
762,13 → 758,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) && (data))
if (msg->dataptr)
*msg->dataptr = *data;
write_barrier();
/branches/dynload/uspace/lib/libc/generic/io/klog.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/console.c
File deleted
/branches/dynload/uspace/lib/libc/generic/io/stream.c
0,0 → 1,86
/*
* 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 <io/io.h>
#include <io/stream.h>
#include <string.h>
#include <malloc.h>
#include <libc.h>
#include <ipc/ipc.h>
#include <ipc/ns.h>
#include <ipc/fb.h>
#include <ipc/services.h>
#include <ipc/console.h>
#include <console.h>
#include <kbd/kbd.h>
#include <unistd.h>
#include <async.h>
#include <sys/types.h>
 
ssize_t read_stdin(void *buf, size_t count)
{
int cons_phone = console_open(false);
if (cons_phone >= 0) {
kbd_event_t ev;
int rc;
size_t i = 0;
while (i < count) {
do {
rc = kbd_get_event(&ev);
if (rc < 0) return -1;
} while (ev.c == 0 || ev.type == KE_RELEASE);
((char *) buf)[i++] = ev.c;
}
return i;
} else
return -1;
}
 
/** Write a string to klog. */
int klog_puts(const char *str)
{
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) str, str_size(str));
}
 
void klog_update(void)
{
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/io.c
30,564 → 30,98
* @{
*/
/** @file
*/
*/
 
#include <libc.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <io/io.h>
#include <string.h>
#include <errno.h>
#include <bool.h>
#include <malloc.h>
#include <io/klog.h>
#include <vfs/vfs.h>
#include <ipc/devmap.h>
#include <adt/list.h>
#include <console.h>
 
static void _fflushbuf(FILE *stream);
const static char nl = '\n';
 
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[])
int puts(const char *str)
{
if (filc > 0) {
stdin = fopen_node(filv[0], "r");
} else {
stdin = &stdin_null;
list_append(&stdin->link, &files);
}
size_t count;
if (filc > 1) {
stdout = fopen_node(filv[1], "w");
} else {
stdout = &stdout_klog;
list_append(&stdout->link, &files);
}
if (str == NULL)
return putnchars("(NULL)", 6);
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;
for (count = 0; str[count] != 0; count++);
while (link != &files) {
FILE *file = list_get_instance(link, FILE, link);
fclose(file);
link = files.next;
if (console_write((void *) str, count) == count) {
if (console_write(&nl, 1) == 1)
return 0;
}
}
 
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;
}
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;
return EOF;
}
 
/** Set stream buffer. */
void setvbuf(FILE *stream, void *buf, int mode, size_t size)
/** 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)
{
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. */
if (console_write((void *) buf, count) == count)
return 0;
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);
}
return EOF;
}
 
/** 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.
/** Same as puts, but does not print newline at end
*
* @param path Path of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*
*/
FILE *fopen(const char *path, const char *mode)
int putstr(const char *str)
{
int flags;
if (!parse_mode(mode, &flags))
return NULL;
size_t count;
/* 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;
}
if (str == NULL)
return putnchars("(NULL)", 6);
 
FILE *fdopen(int fd, const char *mode)
{
/* Open file. */
FILE *stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
for (count = 0; str[count] != 0; count++);
if (console_write((void *) str, count) == count)
return 0;
stream->fd = fd;
stream->error = false;
stream->eof = false;
stream->klog = false;
stream->phone = -1;
_setvbuf(stream);
list_append(&stream->link, &files);
return stream;
return EOF;
}
 
FILE *fopen_node(fdi_node_t *node, const char *mode)
int putchar(int c)
{
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;
}
char buf[STR_BOUNDS(1)];
size_t offs;
 
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() */
offs = 0;
if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK)
return EOF;
}
return 0;
}
 
/** 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);
}
if (console_write((void *) buf, offs) == offs)
return c;
 
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);
return EOF;
}
 
/** Drain stream buffer, do not sync stream. */
static void _fflushbuf(FILE *stream)
int getchar(void)
{
size_t bytes_used;
unsigned char c;
if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error))
return;
console_flush();
if (read_stdin((void *) &c, 1) == 1)
return c;
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 putchar(wchar_t c)
int fflush(FILE *f)
{
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;
/* Dummy implementation */
(void) f;
console_flush();
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/fprintf.c
0,0 → 1,77
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/**
* @file
* @brief fprintf, vfprintf
*/
 
#include <stdio.h>
#include <sys/types.h>
#include <io/printf_core.h>
 
static int vfprintf_str_write(const char *s, size_t size, void *f)
{
/* FIXME: Should return number of characters? */
return fwrite(s, 1, size, (FILE *) f);
}
 
static int vfprintf_wstr_write(const char *s, size_t size, void *f)
{
/* TODO */
return size;
}
 
int vfprintf(FILE *f, const char *fmt, va_list ap)
{
struct printf_spec ps = {
vfprintf_str_write,
vfprintf_wstr_write,
(void *) f
};
 
return printf_core(fmt, &ps, ap);
}
 
int fprintf(FILE *f, const char *fmt, ...)
{
int rv;
va_list args;
 
va_start(args, fmt);
rv = vfprintf(f, fmt, args);
va_end(args);
 
return rv;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/vprintf.c
38,25 → 38,37
#include <io/printf_core.h>
#include <futex.h>
#include <async.h>
#include <string.h>
#include <console.h>
 
static atomic_t printf_futex = FUTEX_INITIALIZER;
 
static int vprintf_str_write(const char *str, size_t size, void *stream)
static int vprintf_str_write(const char *str, size_t size, void *data)
{
size_t wr = fwrite(str, 1, size, (FILE *) stream);
return str_nlength(str, wr);
size_t offset = 0;
size_t prev;
count_t chars = 0;
while (offset < size) {
prev = offset;
str_decode(str, &offset, size);
console_write(str + prev, offset - prev);
chars++;
}
return chars;
}
 
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *stream)
static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
{
size_t offset = 0;
size_t chars = 0;
size_t boff;
count_t chars = 0;
char buf[4];
while (offset < size) {
if (fputc(str[chars], (FILE *) stream) <= 0)
break;
boff = 0;
chr_encode(str[chars], buf, &boff, 4);
console_write(buf, boff);
chars++;
offset += sizeof(wchar_t);
}
64,55 → 76,33
return chars;
}
 
 
/** Print formatted text.
*
* @param stream Output stream
* @param fmt Format string
* @param ap Format parameters
*
* @param fmt format string
* @param ap format parameters
* \see For more details about format string see printf_core.
*
*/
int vfprintf(FILE *stream, const char *fmt, va_list ap)
int vprintf(const char *fmt, va_list ap)
{
struct printf_spec ps = {
vprintf_str_write,
vprintf_wstr_write,
stream
NULL
};
/*
* Prevent other threads to execute printf_core()
*/
futex_down(&printf_futex);
/*
* Prevent other fibrils of the same thread
* Prevent other pseudo threads 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
*/
size_t index = 0;
index_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)
{
size_t index = 0;
index_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)
{
size_t counter = 0;
count_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)
{
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
254,12 → 254,12
return printf_putstr(nullstr, ps);
 
/* Print leading spaces. */
size_t strw = str_length(str);
count_t strw = str_length(str);
if (precision == 0)
precision = strw;
 
/* Left padding */
size_t counter = 0;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
301,6 → 301,9
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)
307,7 → 310,7
precision = strw;
/* Left padding */
size_t counter = 0;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
429,7 → 432,7
}
width -= precision + size - number_size;
size_t counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
592,7 → 595,7
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
size_t counter = 0; /* Number of characters printed */
count_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
/branches/dynload/uspace/lib/libc/generic/io/stdio.c
0,0 → 1,278
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/**
* @file
* @brief ANSI C Stream I/O.
*/
 
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <bool.h>
#include <stdio.h>
 
FILE *stdin, *stdout, *stderr;
 
/**
* Open a stream.
*
* @param file_name Name of the file to open.
* @param mode Mode string, (r|w|a)[b|t][+].
*/
FILE *fopen(const char *file_name, const char *mode)
{
FILE *f;
int flags;
bool plus;
const char *mp;
 
/* Parse mode except first character. */
 
mp = mode;
if (*mp++ == '\0') {
errno = EINVAL;
return NULL;
}
 
if (*mp == 'b' || *mp == 't') ++mp;
 
if (*mp == '+') {
++mp;
plus = true;
} else {
plus = false;
}
 
if (*mp != '\0') {
errno = EINVAL;
return NULL;
}
 
/* Parse first character of mode and determine flags for open(). */
 
switch (mode[0]) {
case 'r':
flags = plus ? O_RDWR : O_RDONLY;
break;
case 'w':
flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
break;
case 'a':
/* TODO: a+ must read from beginning, append to the end. */
if (plus) {
errno = ENOTSUP;
return NULL;
}
flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
default:
errno = EINVAL;
return NULL;
}
 
/* Open file. */
f = malloc(sizeof(FILE));
if (f == NULL) {
errno = ENOMEM;
return NULL;
}
 
f->fd = open(file_name, flags, 0666);
if (f->fd < 0) {
free(f);
return NULL; /* errno was set by open() */
}
 
f->error = 0;
f->eof = 0;
 
return f;
}
 
/** Close a stream.
*
* @param f Pointer to stream.
* @return 0 on success, EOF on error.
*/
int fclose(FILE *f)
{
int rc;
 
rc = close(f->fd);
free(f);
 
if (rc != 0)
return EOF; /* errno was set by close() */
 
return 0;
}
 
/** Read from a stream.
*
* @param buf Destination buffer.
* @param size Size of each record.
* @param nmemb Number of records to read.
* @param f Pointer to the stream.
*/
size_t fread(void *buf, size_t size, size_t nmemb, FILE *f)
{
size_t left, done, n;
 
left = size * nmemb;
done = 0;
 
while (left > 0 && !f->error && !f->eof) {
n = read(f->fd, buf + done, left);
 
if (n < 0) {
f->error = 1;
} else if (n == 0) {
f->eof = 1;
} else {
left -= n;
done += n;
}
}
 
return done / size;
}
 
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param f Pointer to the stream.
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f)
{
size_t left, done, n;
 
left = size * nmemb;
done = 0;
 
while (left > 0 && !f->error) {
n = write(f->fd, buf + done, left);
 
if (n <= 0) {
f->error = 1;
} else {
left -= n;
done += n;
}
}
 
return done / size;
}
 
/** Return the end-of-file indicator of a stream. */
int feof(FILE *f)
{
return f->eof;
}
 
/** Return the error indicator of a stream. */
int ferror(FILE *f)
{
return f->error;
}
 
/** Clear the error and end-of-file indicators of a stream. */
void clearerr(FILE *f)
{
f->eof = 0;
f->error = 0;
}
 
/** Read character from a stream. */
int fgetc(FILE *f)
{
unsigned char c;
size_t n;
 
n = fread(&c, sizeof(c), 1, f);
if (n < 1) return EOF;
 
return (int) c;
}
 
/** Write character to a stream. */
int fputc(int c, FILE *f)
{
unsigned char cc;
size_t n;
 
cc = (unsigned char) c;
n = fwrite(&cc, sizeof(cc), 1, f);
if (n < 1) return EOF;
 
return (int) cc;
}
 
/** Write string to a stream. */
int fputs(const char *s, FILE *f)
{
int rc;
 
rc = 0;
 
while (*s && rc >= 0) {
rc = fputc(*s++, f);
}
 
if (rc < 0) return EOF;
 
return 0;
}
 
/** Seek to position in stream. */
int fseek(FILE *f, long offset, int origin)
{
off_t rc;
 
rc = lseek(f->fd, offset, origin);
if (rc == (off_t) (-1)) {
/* errno has been set by lseek. */
return -1;
}
 
f->eof = 0;
 
return 0;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/sprintf.c
0,0 → 1,57
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <io/printf_core.h>
 
/** Print formatted to the given buffer.
* @param str buffer
* @param fmt format string
* \see For more details about format string see printf_core.
*/
int sprintf(char *str, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
ret = vsprintf(str, fmt, args);
va_end(args);
 
return ret;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/asprintf.c
36,52 → 36,42
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/printf_core.h>
 
static int asprintf_str_write(const char *str, size_t count, void *unused)
static int asprintf_prewrite(const char *str, size_t count, void *unused)
{
return str_nlength(str, count);
return 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 string.
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format strin.
*
* @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_str_write,
asprintf_wstr_write,
NULL
asprintf_prewrite,
NULL
};
int ret;
va_list args;
 
va_start(args, fmt);
int ret = printf_core(fmt, &ps, args);
ret = printf_core(fmt, &ps, args);
va_end(args);
if (ret > 0) {
*strp = malloc(STR_BOUNDS(ret) + 1);
if (*strp == NULL)
*strp = malloc(ret + 20);
if (!*strp)
return -1;
va_start(args, fmt);
vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args);
va_end(args);
vsprintf(*strp, fmt, args);
va_end(args);
}
 
return ret;
}
 
/branches/dynload/uspace/lib/libc/generic/io/printf.c
34,43 → 34,23
 
#include <io/printf_core.h>
#include <stdio.h>
#include <stdio.h>
 
/** Print formatted text.
*
* @param stream Output stream
* @param fmt Format string
*
* @param fmt format string
* \see For more details about format string see printf_core.
*
*/
int fprintf(FILE *stream, const char *fmt, ...)
int printf(const char *fmt, ...)
{
int ret;
va_list args;
 
va_start(args, fmt);
 
ret = vprintf(fmt, args);
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, ...)
{
va_list args;
va_start(args, fmt);
int ret = vprintf(fmt, args);
va_end(args);
return ret;
}
 
/branches/dynload/uspace/lib/libc/generic/io/vsprintf.c
0,0 → 1,51
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <io/printf_core.h>
 
/** Print formatted to the given buffer.
* @param str buffer
* @param fmt format string
* @param ap argument list
* \see For more details about format string see printf_core.
*/
int vsprintf(char *str, const char *fmt, va_list ap)
{
return vsnprintf(str, (size_t) - 1, fmt, ap);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/io/snprintf.c
37,23 → 37,21
#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);
int ret = vsnprintf(str, size, fmt, args);
ret = vsnprintf(str, size, fmt, args);
 
va_end(args);
 
return ret;
}
 
/branches/dynload/uspace/lib/libc/generic/kbd.c
0,0 → 1,62
/*
* Copyright (c) 2009 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <io/stream.h>
#include <kbd/kbd.h>
#include <ipc/ipc.h>
#include <ipc/console.h>
#include <console.h>
#include <async.h>
 
int kbd_get_event(kbd_event_t *ev)
{
int cons_phone = console_open(true);
ipcarg_t r0, r1, r2, r3;
int rc;
 
rc = async_req_0_4(cons_phone, CONSOLE_GETKEY, &r0, &r1, &r2, &r3);
if (rc < 0)
return -1;
 
ev->type = r0;
ev->key = r1;
ev->mods = r2;
ev->c = r3;
 
return 0;
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/task.c
31,7 → 31,7
* @{
*/
/** @file
*/
*/
 
#include <task.h>
#include <libc.h>
39,25 → 39,21
#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)
{
69,102 → 65,58
* 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 args[])
task_id_t task_spawn(const char *path, char *const argv[])
{
loader_t *ldr;
task_id_t task_id;
int rc;
 
/* Connect to a program loader. */
loader_t *ldr = loader_connect();
ldr = loader_connect();
if (ldr == NULL)
return 0;
 
/* Get task ID. */
task_id_t task_id;
int rc = loader_get_task_id(ldr, &task_id);
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, args);
rc = loader_set_args(ldr, argv);
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 exit */
error:
/* Error exit */
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/console.c
0,0 → 1,274
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2006 Jakub Vana
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <libc.h>
#include <async.h>
#include <io/stream.h>
#include <ipc/console.h>
#include <ipc/services.h>
#include <errno.h>
#include <string.h>
#include <console.h>
 
static int console_phone = -1;
 
/** Size of cbuffer. */
#define CBUFFER_SIZE 256
 
/** Buffer for writing characters to the console. */
static char cbuffer[CBUFFER_SIZE];
 
/** Pointer to end of cbuffer. */
static char *cbuffer_end = cbuffer + CBUFFER_SIZE;
 
/** Pointer to first available field in cbuffer. */
static char *cbp = cbuffer;
 
 
/** Write one character to the console via IPC. */
static void cons_putchar(wchar_t c)
{
console_wait();
async_msg_1(console_phone, CONSOLE_PUTCHAR, c);
}
 
/** Write characters to the console via IPC or to klog */
static ssize_t cons_write(const char *buf, size_t size)
{
console_open(false);
if (console_phone >= 0) {
async_serialize_start();
ipc_call_t answer;
aid_t req = async_send_0(console_phone, CONSOLE_WRITE, &answer);
ipcarg_t rc = ipc_data_write_start(console_phone, (void *) buf, size);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
return (ssize_t) rc;
}
async_wait_for(req, &rc);
async_serialize_end();
if (rc == EOK)
return (ssize_t) IPC_GET_ARG1(answer);
else
return -1;
} else
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
}
 
/** Write all data from output buffer to the console. */
static void cbuffer_flush(void)
{
size_t len = cbp - cbuffer;
while (len > 0) {
ssize_t rc = cons_write(cbuffer, cbp - cbuffer);
if (rc < 0)
return;
len -= rc;
}
cbp = cbuffer;
}
 
/** Drop all data in console output buffer. */
static void cbuffer_drain(void)
{
cbp = cbuffer;
}
 
/** Write one character to the output buffer. */
static inline void cbuffer_putc(char c)
{
if (cbp == cbuffer_end)
cbuffer_flush();
*cbp++ = c;
if (c == '\n')
cbuffer_flush();
}
 
int console_open(bool blocking)
{
if (console_phone < 0) {
int phone;
if (blocking)
phone = ipc_connect_me_to_blocking(PHONE_NS,
SERVICE_CONSOLE, 0, 0);
else
phone = ipc_connect_me_to(PHONE_NS,
SERVICE_CONSOLE, 0, 0);
if (phone >= 0)
console_phone = phone;
}
return console_phone;
}
 
void console_close(void)
{
if (console_phone >= 0) {
if (ipc_hangup(console_phone) == 0)
console_phone = -1;
}
}
 
void console_wait(void)
{
while (console_phone < 0)
console_open(true);
}
 
void console_clear(void)
{
console_wait();
cbuffer_drain();
async_msg_0(console_phone, CONSOLE_CLEAR);
}
 
int console_get_size(int *rows, int *cols)
{
console_wait();
ipcarg_t r;
ipcarg_t c;
int rc = async_req_0_2(console_phone, CONSOLE_GETSIZE, &r, &c);
*rows = (int) r;
*cols = (int) c;
return rc;
}
 
void console_set_style(int style)
{
console_wait();
cbuffer_flush();
async_msg_1(console_phone, CONSOLE_SET_STYLE, style);
}
 
void console_set_color(int fg_color, int bg_color, int flags)
{
console_wait();
cbuffer_flush();
async_msg_3(console_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
}
 
void console_set_rgb_color(int fg_color, int bg_color)
{
console_wait();
cbuffer_flush();
async_msg_2(console_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
}
 
void console_cursor_visibility(int show)
{
console_wait();
cbuffer_flush();
async_msg_1(console_phone, CONSOLE_CURSOR_VISIBILITY, show != 0);
}
 
void console_kcon_enable(void)
{
console_wait();
cbuffer_flush();
async_msg_0(console_phone, CONSOLE_KCON_ENABLE);
}
 
void console_goto(int row, int col)
{
console_wait();
cbuffer_flush();
async_msg_2(console_phone, CONSOLE_GOTO, row, col);
}
 
void console_putchar(wchar_t c)
{
console_wait();
cbuffer_flush();
cons_putchar(c);
}
 
/** Write characters to the console. */
ssize_t console_write(const char *buf, size_t size)
{
size_t left = size;
while (left > 0) {
cbuffer_putc(*buf++);
left--;
}
return size;
}
 
/** Write a NULL-terminated string to the console. */
void console_putstr(const char *str)
{
size_t left = str_size(str);
while (left > 0) {
ssize_t rc = console_write(str, left);
if (rc < 0) {
/* Error */
return;
}
str += rc;
left -= rc;
}
}
 
/** Flush all output to the console or klog. */
void console_flush(void)
{
cbuffer_flush();
if (console_phone >= 0)
async_msg_0(console_phone, CONSOLE_FLUSH);
}
 
/** @}
*/
/branches/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 */
const char *optarg; /* argument associated with option */
char *optarg; /* argument associated with option */
 
 
#define IGNORE_FIRST (*options == '-' || *options == '+')
162,7 → 162,7
char **nargv;
const char *options;
{
const char *oli; /* option letter list index */
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,8 → 353,7
 
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
char *current_argv;
const char *has_equal;
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
 
/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, size_t max_len)
size_t str_lsize(const char *str, count_t max_len)
{
size_t len = 0;
count_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, size_t max_len)
size_t wstr_lsize(const wchar_t *str, count_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.
*
*/
size_t str_length(const char *str)
count_t str_length(const char *str)
{
size_t len = 0;
count_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.
*
*/
size_t wstr_length(const wchar_t *wstr)
count_t wstr_length(const wchar_t *wstr)
{
size_t len = 0;
count_t len = 0;
while (*wstr++ != 0)
len++;
319,9 → 319,9
* @return Number of characters in string.
*
*/
size_t str_nlength(const char *str, size_t size)
count_t str_nlength(const char *str, size_t size)
{
size_t len = 0;
count_t len = 0;
size_t offset = 0;
while (str_decode(str, &offset, size) != 0)
338,11 → 338,11
* @return Number of characters in string.
*
*/
size_t wstr_nlength(const wchar_t *str, size_t size)
count_t wstr_nlength(const wchar_t *str, size_t size)
{
size_t len = 0;
size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
size_t offset = 0;
count_t len = 0;
count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
count_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, size_t max_len)
int str_lcmp(const char *s1, const char *s2, count_t max_len)
{
wchar_t c1 = 0;
wchar_t c2 = 0;
438,7 → 438,7
size_t off1 = 0;
size_t off2 = 0;
size_t len = 0;
count_t len = 0;
 
while (true) {
if (len >= max_len)
568,7 → 568,7
return;
wchar_t ch;
size_t src_idx = 0;
count_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.
*/
char *str_chr(const char *str, wchar_t ch)
const 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 (char *) (str + last);
return (str + last);
last = off;
}
611,12 → 611,12
*
* @return Pointer to character in @a str or NULL if not found.
*/
char *str_rchr(const char *str, wchar_t ch)
const char *str_rchr(const char *str, wchar_t ch)
{
wchar_t acc;
size_t off = 0;
size_t last = 0;
const char *res = NULL;
char *res = NULL;
while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
if (acc == ch)
624,7 → 624,7
last = off;
}
return (char *) res;
return 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, size_t pos, size_t max_pos)
bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
{
size_t len = wstr_length(str);
count_t len = wstr_length(str);
if ((pos > len) || (pos + 1 > max_pos))
return false;
size_t i;
count_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, size_t pos)
bool wstr_remove(wchar_t *str, count_t pos)
{
size_t len = wstr_length(str);
count_t len = wstr_length(str);
if (pos >= len)
return false;
size_t i;
count_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,12 → 47,9
/** 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
* deallocated using free() after use).
*
* @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).
*/
int loader_spawn(const char *name)
{
62,16 → 59,19
 
loader_t *loader_connect(void)
{
int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
loader_t *ldr;
int phone_id;
 
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
if (phone_id < 0)
return NULL;
loader_t *ldr = malloc(sizeof(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,26 → 78,27
*
* 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)
{
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
/* Get task ID. */
ipc_call_t answer;
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));
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));
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.
106,35 → 107,39
* 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;
char *pa = absolutize(path, &pa_len);
 
pa = absolutize(path, &pa_len);
if (!pa)
return 0;
 
/* Send program pathname */
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);
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
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
141,110 → 146,61
* 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.
*/
char *const *ap = argv;
size_t buffer_size = 0;
ap = argv;
buffer_size = 0;
while (*ap != NULL) {
buffer_size += str_size(*ap) + 1;
ap++;
++ap;
}
char *arg_buf = malloc(buffer_size);
if (arg_buf == NULL)
return ENOMEM;
 
arg_buf = malloc(buffer_size);
if (arg_buf == NULL) return ENOMEM;
 
/* Now fill the buffer with null-terminated argument strings */
ap = argv;
char *dp = arg_buf;
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 */
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);
 
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
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;
}
 
253,14 → 209,18
* 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)
{
return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
int rc;
 
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
if (rc != EOK)
return rc;
 
return EOK;
}
 
/** Instruct loader to execute the program.
272,17 → 232,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 = async_req_0_0(ldr->phone_id, LOADER_RUN);
int rc;
 
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;
294,10 → 254,8
* 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/libc.c
27,29 → 27,28
*/
 
/** @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. */
56,8 → 55,11
#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);
65,19 → 67,18
 
void __main(void *pcb_ptr)
{
int retval;
fibril_t *f;
int argc;
char **argv;
 
__heap_init();
__async_init();
fibril_t *fibril = fibril_setup();
__tcb_set(fibril->tcb);
(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;
int argc;
char **argv;
__pcb = (pcb_t *)pcb_ptr;
 
#ifdef __IN_SHARED_LIBC__
if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
runtime_env = (runtime_env_t *) __pcb->rtld_runtime;
87,17 → 88,13
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);
 
__stdio_done();
(void) task_retval(retval);
main(argc, argv);
console_flush();
}
 
void __exit(void)
/branches/dynload/uspace/lib/libc/generic/vfs/vfs.c
38,8 → 38,8
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
48,14 → 48,13
#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"
 
static int vfs_phone = -1;
static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
static futex_t cwd_futex = FUTEX_INITIALIZER;
int vfs_phone = -1;
futex_t vfs_phone_futex = FUTEX_INITIALIZER;
 
futex_t cwd_futex = FUTEX_INITIALIZER;
DIR *cwd_dir = NULL;
char *cwd_path = NULL;
size_t cwd_size = 0;
116,8 → 115,47
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, unsigned int flags)
const char *opts, const unsigned int flags)
{
int res;
ipcarg_t rc;
124,7 → 162,7
aid_t req;
dev_handle_t dev_handle;
res = devmap_device_get_handle(dev, &dev_handle, flags);
res = device_get_handle(dev, &dev_handle, flags);
if (res != EOK)
return res;
137,7 → 175,7
async_serialize_start();
vfs_connect();
req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL);
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
198,7 → 236,7
async_serialize_start();
vfs_connect();
req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
211,10 → 249,9
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
 
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
223,27 → 260,6
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;
252,7 → 268,7
async_serialize_start();
vfs_connect();
rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
async_serialize_end();
futex_up(&vfs_phone_futex);
270,7 → 286,7
async_serialize_start();
vfs_connect();
req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
async_wait_for(req, NULL);
297,7 → 313,7
async_serialize_start();
vfs_connect();
req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
if (rc != EOK) {
async_wait_for(req, NULL);
314,20 → 330,6
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;
337,7 → 339,7
vfs_connect();
ipcarg_t newoffs;
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
&newoffs);
 
async_serialize_end();
357,74 → 359,12
async_serialize_start();
vfs_connect();
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
rc = async_req_2_0(vfs_phone, VFS_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));
472,7 → 412,7
async_serialize_start();
vfs_connect();
req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
485,7 → 425,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
static int _unlink(const char *path, int lflag)
502,7 → 442,7
async_serialize_start();
vfs_connect();
req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
if (rc != EOK) {
async_wait_for(req, NULL);
515,7 → 455,7
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
return rc;
return rc;
}
 
int unlink(const char *path)
549,7 → 489,7
async_serialize_start();
vfs_connect();
req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
req = async_send_0(vfs_phone, VFS_RENAME, NULL);
rc = ipc_data_write_start(vfs_phone, olda, olda_size);
if (rc != EOK) {
async_wait_for(req, NULL);
618,34 → 558,5
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/ddi.c
127,10 → 127,10
}
#endif
 
phys = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
offset = pio_addr - phys;
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
virt = as_get_mappable_page(pages << PAGE_WIDTH);
virt = as_get_mappable_page(pages);
*use_addr = virt + offset;
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
}
/branches/dynload/uspace/lib/libc/generic/ipc.c
43,7 → 43,7
#include <libc.h>
#include <malloc.h>
#include <errno.h>
#include <adt/list.h>
#include <libadt/list.h>
#include <stdio.h>
#include <unistd.h>
#include <futex.h>
232,7 → 232,7
return;
}
 
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
if (callid == IPC_CALLRET_FATAL) {
futex_up(&ipc_futex);
/* Call asynchronous handler with error code */
if (call->callback)
241,7 → 241,7
return;
}
 
if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
if (callid == 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_callid_t) IPC_CALLRET_TEMPORARY) {
if (callid == 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_callid_t) IPC_CALLRET_TEMPORARY) {
if (callid == IPC_CALLRET_TEMPORARY) {
break;
}
list_remove(&call->list);
451,7 → 451,7
if (call->fid)
fibril_add_ready(call->fid);
if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
if (callid == 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 __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode);
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode);
}
 
/** Wrapper for making IPC_M_SHARE_IN calls.
/branches/dynload/uspace/lib/libc/generic/mem.c
95,7 → 95,7
 
static void *unaligned_memcpy(void *dst, const void *src, size_t n)
{
size_t i, j;
int i, j;
struct along *adst = dst;
const struct along *asrc = src;
 
/branches/dynload/uspace/lib/libc/generic/fibril.c
33,7 → 33,7
/** @file
*/
 
#include <adt/list.h>
#include <libadt/list.h>
#include <fibril.h>
#include <thread.h>
#include <tls.h>
49,8 → 49,7
#define FIBRIL_INITIAL_STACK_PAGES_NO 1
#endif
 
/**
* This futex serializes access to ready_list, serialized_list and manager_list.
/** This futex serializes access to ready_list, serialized_list and manage_list.
*/
static atomic_t fibril_futex = FUTEX_INITIALIZER;
 
60,12 → 59,12
 
static void fibril_main(void);
 
/** 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;
/** 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;
 
/** Setup fibril information into TCB structure */
fibril_t *fibril_setup(void)
144,11 → 143,11
if (list_empty(&ready_list) && list_empty(&serialized_list))
goto ret_0;
/*
* Do not preempt if there is not enough threads to run the
* ready fibrils which are not serialized.
* Do not preempt if there is not sufficient count of fibril
* managers.
*/
if (list_empty(&serialized_list) &&
threads_in_manager <= serialized_threads) {
fibrils_in_manager <= serialized_fibrils) {
goto ret_0;
}
}
195,7 → 194,7
list_append(&srcf->link, &ready_list);
else if (stype == FIBRIL_FROM_MANAGER) {
list_append(&srcf->link, &manager_list);
threads_in_manager--;
fibrils_in_manager--;
} else {
/*
* If stype == FIBRIL_TO_MANAGER, don't put ourselves to
209,10 → 208,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_threads++;
serialized_fibrils++;
srcf->flags |= FIBRIL_SERIALIZED;
}
threads_in_manager++;
fibrils_in_manager++;
 
if (stype == FIBRIL_FROM_DEAD)
dstf->clean_after_me = srcf;
220,7 → 219,7
if (!list_empty(&serialized_list)) {
dstf = list_get_instance(serialized_list.next, fibril_t,
link);
serialized_threads--;
serialized_fibrils--;
} else {
dstf = list_get_instance(ready_list.next, fibril_t,
link);
270,7 → 269,7
 
/** Add a fibril to the ready list.
*
* @param fid Pointer to the fibril structure of the fibril to be
* @param fid Pinter to the fibril structure of the fibril to be
* added.
*/
void fibril_add_ready(fid_t fid)
288,8 → 287,7
 
/** Add a fibril to the manager list.
*
* @param fid Pointer to the fibril structure of the fibril to be
* added.
* @param fid Pinter to the fibril structure of the fibril to be added.
*/
void fibril_add_manager(fid_t fid)
{
316,8 → 314,7
 
/** Return fibril id of the currently running fibril.
*
* @return fibril ID of the currently running fibril.
*
* @return Fibril ID of the currently running pseudo thread.
*/
fid_t fibril_get_id(void)
{
324,14 → 321,13
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.
*
* futex as well. Interrupt messages can still be preempted.
*/
void fibril_inc_sercount(void)
{
/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>
 
/** Last position allocated by as_get_mappable_page */
static uintptr_t last_allocated = 0;
/**
* Either 4*256M on 32-bit architecures or 16*256M on 64-bit architectures.
*/
#define MAX_HEAP_SIZE (sizeof(uintptr_t)<<28)
 
/** 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,16 → 61,15
/** 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);
}
 
77,24 → 76,22
/** 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)
{
102,29 → 99,101
(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 size Requested size of the allocation.
* @param sz 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 size)
void *as_get_mappable_page(size_t sz)
{
if (size == 0)
return NULL;
void *res;
uint64_t asz;
int i;
size_t sz = 1 << (fnzb(size - 1) + 1);
if (last_allocated == 0)
last_allocated = get_max_heap_addr();
if (!sz)
return NULL;
 
asz = 1 << (fnzb64(sz - 1) + 1);
 
/* Set heapsize to some meaningful value */
if (maxheapsize == -1)
set_maxheapsize(MAX_HEAP_SIZE);
/*
* Make sure we allocate from naturally aligned address.
*/
uintptr_t res = ALIGN_UP(last_allocated, sz);
last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
return ((void *) res);
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;
}
 
/** @}
/branches/dynload/uspace/lib/libc/generic/libadt/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 <libadt/hash_table.h>
#include <libadt/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/libadt/list.c
0,0 → 1,89
/*
* 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 <libadt/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 = false;
link_t *hlp = head->next;
while (hlp != head) {
if (hlp == link) {
found = true;
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);
}
 
/** @}
*/
/branches/dynload/uspace/lib/libc/generic/mman.c
37,18 → 37,17
#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,7 → 33,6
LIBC_PREFIX = $(shell pwd)
SOFTINT_PREFIX = ../softint
 
 
## Setup toolchain
#
 
51,13 → 50,11
generic/ddi.c \
generic/as.c \
generic/cap.c \
generic/devmap.c \
generic/console.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 \
67,13 → 64,16
generic/io/asprintf.c \
generic/io/io.c \
generic/io/printf.c \
generic/io/klog.c \
generic/io/fprintf.c \
generic/io/stdio.c \
generic/io/stream.c \
generic/io/sprintf.c \
generic/io/snprintf.c \
generic/io/vprintf.c \
generic/io/vsprintf.c \
generic/io/vsnprintf.c \
generic/io/printf_core.c \
generic/io/console.c \
generic/malloc.c \
malloc/malloc.c \
generic/sysinfo.c \
generic/ipc.c \
generic/async.c \
80,11 → 80,12
generic/dlfcn.c \
generic/loader.c \
generic/getopt.c \
generic/adt/list.o \
generic/adt/hash_table.o \
generic/libadt/list.o \
generic/libadt/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/rtld/include/rtld.h
36,7 → 36,7
#define RTLD_H_
 
#include <sys/types.h>
#include <adt/list.h>
#include <libadt/list.h>
 
#include <dynamic.h>
#include <module.h>
/branches/dynload/uspace/lib/libc/rtld/include/module.h
37,7 → 37,7
 
#include <sys/types.h>
#include <dynamic.h>
#include <adt/list.h>
#include <libadt/list.h>
 
typedef struct module {
dyn_info_t dyn;
/branches/dynload/uspace/lib/libc/rtld/module.c
38,7 → 38,7
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <adt/list.h>
#include <libadt/list.h>
#include <loader/pcb.h>
 
#include <rtld.h>
/branches/dynload/uspace/lib/libc/Makefile.toolchain
26,11 → 26,10
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
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)__
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration \
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \
-Wmissing-prototypes -O3 -nostdlib -nostdinc -imacros \
$(LIBC_PREFIX)/../../../config.h -I$(LIBC_PREFIX)/include -pipe -g
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
 
/branches/dynload/uspace/lib/libc/arch/sparc64/include/types.h
49,6 → 49,8
 
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/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 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 libcsparc64
* @{
*/
/** @file
*/
 
#ifndef LIBC_sparc64_BYTEORDER_H_
#define LIBC_sparc64_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/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 + STACK_ARG_SAVE_AREA_SIZE)
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE
 
#ifdef context_set
#undef context_set
/branches/dynload/uspace/lib/libc/arch/sparc64/include/stack.h
45,11 → 45,6
*/
#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/Makefile.inc
38,7 → 38,5
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/types.h
49,6 → 49,8
 
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/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 libcia64
* @{
*/
/** @file
*/
 
#ifndef LIBC_ia64_BYTEORDER_H_
#define LIBC_ia64_BYTEORDER_H_
 
/* IA-64 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/ia64/Makefile.inc
31,6 → 31,9
 
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 \
37,10 → 40,5
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/types.h
50,6 → 50,8
 
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/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 libcarm32
* @{
*/
/** @file
* @brief Endianness definitions.
*/
 
#ifndef LIBC_arm32_BYTEORDER_H_
#define LIBC_arm32_BYTEORDER_H_
 
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/arm32/include/tls.h
40,7 → 40,7
 
#define CONFIG_TLS_VARIANT_1
 
/** Offsets for accessing thread-local variables are shifted 8 bytes higher. */
/** Offsets for accessing __thread variables are shifted 8 bytes higher. */
#define ARM_TP_OFFSET (-8)
 
/** TCB (Thread Control Block) struct.
/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,6 → 32,9
 
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 \
38,10 → 41,5
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/ppc32/include/types.h
49,6 → 49,8
 
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/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 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 libcppc32
* @{
*/
/** @file
*/
 
#ifndef LIBC_ppc32_BYTEORDER_H_
#define LIBC_ppc32_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/ppc32/Makefile.inc
40,7 → 40,5
AFLAGS += -a32
LFLAGS += -N
 
ENDIANESS = BE
 
BFD_NAME = elf32-powerpc
BFD_ARCH = powerpc:common
/branches/dynload/uspace/lib/libc/arch/amd64/include/types.h
49,6 → 49,8
 
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/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 libcamd64
* @{
*/
/** @file
*/
 
#ifndef LIBC_amd64_BYTEORDER_H_
#define LIBC_amd64_BYTEORDER_H_
 
/* AMD64 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/amd64/Makefile.inc
38,7 → 38,5
 
LFLAGS += -N
 
ENDIANESS = LE
 
BFD_NAME = elf64-x86-64
BFD_ARCH = i386:x86-64
/branches/dynload/uspace/lib/libc/arch/mips32/include/types.h
50,6 → 50,8
 
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/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 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 libcmips32
* @{
*/
/** @file
*/
 
#ifndef LIBC_mips32_BYTEORDER_H_
#define LIBC_mips32_BYTEORDER_H_
 
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/mips32/Makefile.inc
31,14 → 31,11
 
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/types.h
49,6 → 49,8
 
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/include/byteorder.h
0,0 → 1,44
/*
* Copyright (c) 2005 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 libcia32
* @{
*/
/** @file
*/
 
#ifndef LIBC_ia32_BYTEORDER_H_
#define LIBC_ia32_BYTEORDER_H_
 
/* IA-32 is little-endian */
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/ia32/Makefile.inc
39,7 → 39,5
 
LFLAGS += -N
 
ENDIANESS = LE
 
BFD_NAME = elf32-i386
BFD_ARCH = i386
/branches/dynload/uspace/lib/libc/arch/mips32eb/include/byteorder.h
0,0 → 1,43
/*
* Copyright (c) 2005 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 libcmips32
* @{
*/
/** @file
*/
 
#ifndef LIBC_mips32eb_BYTEORDER_H_
#define LIBC_mips32eb_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
 
#endif
 
/** @}
*/
/branches/dynload/uspace/lib/libc/arch/mips32eb/Makefile.inc
31,15 → 31,13
 
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/malloc/malloc.c
0,0 → 1,4431
#include <stdio.h>
#include <libc.h>
/*
This is a version (aka dlmalloc) of malloc/free/realloc written by
Doug Lea and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain. Send questions,
comments, complaints, performance data, etc to dl@cs.oswego.edu
 
* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee)
 
Note: There may be an updated version of this malloc obtainable at
ftp://gee.cs.oswego.edu/pub/misc/malloc.c
Check before installing!
 
* Quickstart
 
This library is all in one file to simplify the most common usage:
ftp it, compile it (-O3), and link it into another program. All of
the compile-time options default to reasonable values for use on
most platforms. You might later want to step through various
compile-time and dynamic tuning options.
 
For convenience, an include file for code using this malloc is at:
ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
You don't really need this .h file unless you call functions not
defined in your system include files. The .h file contains only the
excerpts from this file needed for using this malloc on ANSI C/C++
systems, so long as you haven't changed compile-time options about
naming and tuning parameters. If you do, then you can create your
own malloc.h that does include all settings by cutting at the point
indicated below. Note that you may already by default be using a C
library containing a malloc that is based on some version of this
malloc (for example in linux). You might still want to use the one
in this file to customize settings or to avoid overheads associated
with library versions.
 
* Vital statistics:
 
Supported pointer/size_t representation: 4 or 8 bytes
size_t MUST be an unsigned type of the same width as
pointers. (If you are using an ancient system that declares
size_t as a signed type, or need it to be a different width
than pointers, you can use a previous release of this malloc
(e.g. 2.7.2) supporting these.)
 
Alignment: 8 bytes (default)
This suffices for nearly all current machines and C compilers.
However, you can define MALLOC_ALIGNMENT to be wider than this
if necessary (up to 128bytes), at the expense of using more space.
 
Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes)
8 or 16 bytes (if 8byte sizes)
Each malloced chunk has a hidden word of overhead holding size
and status information, and additional cross-check word
if FOOTERS is defined.
 
Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead)
8-byte ptrs: 32 bytes (including overhead)
 
Even a request for zero bytes (i.e., malloc(0)) returns a
pointer to something of the minimum allocatable size.
The maximum overhead wastage (i.e., number of extra bytes
allocated than were requested in malloc) is less than or equal
to the minimum size, except for requests >= mmap_threshold that
are serviced via mmap(), where the worst case wastage is about
32 bytes plus the remainder from a system page (the minimal
mmap unit); typically 4096 or 8192 bytes.
 
Security: static-safe; optionally more or less
The "security" of malloc refers to the ability of malicious
code to accentuate the effects of errors (for example, freeing
space that is not currently malloc'ed or overwriting past the
ends of chunks) in code that calls malloc. This malloc
guarantees not to modify any memory locations below the base of
heap, i.e., static variables, even in the presence of usage
errors. The routines additionally detect most improper frees
and reallocs. All this holds as long as the static bookkeeping
for malloc itself is not corrupted by some other means. This
is only one aspect of security -- these checks do not, and
cannot, detect all possible programming errors.
 
If FOOTERS is defined nonzero, then each allocated chunk
carries an additional check word to verify that it was malloced
from its space. These check words are the same within each
execution of a program using malloc, but differ across
executions, so externally crafted fake chunks cannot be
freed. This improves security by rejecting frees/reallocs that
could corrupt heap memory, in addition to the checks preventing
writes to statics that are always on. This may further improve
security at the expense of time and space overhead. (Note that
FOOTERS may also be worth using with MSPACES.)
 
By default detected errors cause the program to abort (calling
"abort()"). You can override this to instead proceed past
errors by defining PROCEED_ON_ERROR. In this case, a bad free
has no effect, and a malloc that encounters a bad address
caused by user overwrites will ignore the bad address by
dropping pointers and indices to all known memory. This may
be appropriate for programs that should continue if at all
possible in the face of programming errors, although they may
run out of memory because dropped memory is never reclaimed.
 
If you don't like either of these options, you can define
CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
else. And if if you are sure that your program using malloc has
no errors or vulnerabilities, you can define INSECURE to 1,
which might (or might not) provide a small performance improvement.
 
Thread-safety: NOT thread-safe unless USE_LOCKS defined
When USE_LOCKS is defined, each public call to malloc, free,
etc is surrounded with either a pthread mutex or a win32
spinlock (depending on WIN32). This is not especially fast, and
can be a major bottleneck. It is designed only to provide
minimal protection in concurrent environments, and to provide a
basis for extensions. If you are using malloc in a concurrent
program, consider instead using ptmalloc, which is derived from
a version of this malloc. (See http://www.malloc.de).
 
System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
This malloc can use unix sbrk or any emulation (invoked using
the CALL_MORECORE macro) and/or mmap/munmap or any emulation
(invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
memory. On most unix systems, it tends to work best if both
MORECORE and MMAP are enabled. On Win32, it uses emulations
based on VirtualAlloc. It also uses common C library functions
like memset.
 
Compliance: I believe it is compliant with the Single Unix Specification
(See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
others as well.
 
* Overview of algorithms
 
This is not the fastest, most space-conserving, most portable, or
most tunable malloc ever written. However it is among the fastest
while also being among the most space-conserving, portable and
tunable. Consistent balance across these factors results in a good
general-purpose allocator for malloc-intensive programs.
 
In most ways, this malloc is a best-fit allocator. Generally, it
chooses the best-fitting existing chunk for a request, with ties
broken in approximately least-recently-used order. (This strategy
normally maintains low fragmentation.) However, for requests less
than 256bytes, it deviates from best-fit when there is not an
exactly fitting available chunk by preferring to use space adjacent
to that used for the previous small request, as well as by breaking
ties in approximately most-recently-used order. (These enhance
locality of series of small allocations.) And for very large requests
(>= 256Kb by default), it relies on system memory mapping
facilities, if supported. (This helps avoid carrying around and
possibly fragmenting memory used only for large chunks.)
 
All operations (except malloc_stats and mallinfo) have execution
times that are bounded by a constant factor of the number of bits in
a size_t, not counting any clearing in calloc or copying in realloc,
or actions surrounding MORECORE and MMAP that have times
proportional to the number of non-contiguous regions returned by
system allocation routines, which is often just 1.
 
The implementation is not very modular and seriously overuses
macros. Perhaps someday all C compilers will do as good a job
inlining modular code as can now be done by brute-force expansion,
but now, enough of them seem not to.
 
Some compilers issue a lot of warnings about code that is
dead/unreachable only on some platforms, and also about intentional
uses of negation on unsigned types. All known cases of each can be
ignored.
 
For a longer but out of date high-level description, see
http://gee.cs.oswego.edu/dl/html/malloc.html
 
* MSPACES
If MSPACES is defined, then in addition to malloc, free, etc.,
this file also defines mspace_malloc, mspace_free, etc. These
are versions of malloc routines that take an "mspace" argument
obtained using create_mspace, to control all internal bookkeeping.
If ONLY_MSPACES is defined, only these versions are compiled.
So if you would like to use this allocator for only some allocations,
and your system malloc for others, you can compile with
ONLY_MSPACES and then do something like...
static mspace mymspace = create_mspace(0,0); // for example
#define mymalloc(bytes) mspace_malloc(mymspace, bytes)
 
(Note: If you only need one instance of an mspace, you can instead
use "USE_DL_PREFIX" to relabel the global malloc.)
 
You can similarly create thread-local allocators by storing
mspaces as thread-locals. For example:
static __thread mspace tlms = 0;
void* tlmalloc(size_t bytes) {
if (tlms == 0) tlms = create_mspace(0, 0);
return mspace_malloc(tlms, bytes);
}
void tlfree(void* mem) { mspace_free(tlms, mem); }
 
Unless FOOTERS is defined, each mspace is completely independent.
You cannot allocate from one and free to another (although
conformance is only weakly checked, so usage errors are not always
caught). If FOOTERS is defined, then each chunk carries around a tag
indicating its originating mspace, and frees are directed to their
originating spaces.
 
------------------------- Compile-time options ---------------------------
 
Be careful in setting #define values for numerical constants of type
size_t. On some systems, literal values are not automatically extended
to size_t precision unless they are explicitly casted.
 
WIN32 default: defined if _WIN32 defined
Defining WIN32 sets up defaults for MS environment and compilers.
Otherwise defaults are for unix.
 
MALLOC_ALIGNMENT default: (size_t)8
Controls the minimum alignment for malloc'ed chunks. It must be a
power of two and at least 8, even on machines for which smaller
alignments would suffice. It may be defined as larger than this
though. Note however that code and data structures are optimized for
the case of 8-byte alignment.
 
MSPACES default: 0 (false)
If true, compile in support for independent allocation spaces.
This is only supported if HAVE_MMAP is true.
 
ONLY_MSPACES default: 0 (false)
If true, only compile in mspace versions, not regular versions.
 
USE_LOCKS default: 0 (false)
Causes each call to each public routine to be surrounded with
pthread or WIN32 mutex lock/unlock. (If set true, this can be
overridden on a per-mspace basis for mspace versions.)
 
FOOTERS default: 0
If true, provide extra checking and dispatching by placing
information in the footers of allocated chunks. This adds
space and time overhead.
 
INSECURE default: 0
If true, omit checks for usage errors and heap space overwrites.
 
USE_DL_PREFIX default: NOT defined
Causes compiler to prefix all public routines with the string 'dl'.
This can be useful when you only want to use this malloc in one part
of a program, using your regular system malloc elsewhere.
 
ABORT default: defined as abort()
Defines how to abort on failed checks. On most systems, a failed
check cannot die with an "assert" or even print an informative
message, because the underlying print routines in turn call malloc,
which will fail again. Generally, the best policy is to simply call
abort(). It's not very useful to do more than this because many
errors due to overwriting will show up as address faults (null, odd
addresses etc) rather than malloc-triggered checks, so will also
abort. Also, most compilers know that abort() does not return, so
can better optimize code conditionally calling it.
 
PROCEED_ON_ERROR default: defined as 0 (false)
Controls whether detected bad addresses cause them to bypassed
rather than aborting. If set, detected bad arguments to free and
realloc are ignored. And all bookkeeping information is zeroed out
upon a detected overwrite of freed heap space, thus losing the
ability to ever return it from malloc again, but enabling the
application to proceed. If PROCEED_ON_ERROR is defined, the
static variable malloc_corruption_error_count is compiled in
and can be examined to see if errors have occurred. This option
generates slower code than the default abort policy.
 
DEBUG default: NOT defined
The DEBUG setting is mainly intended for people trying to modify
this code or diagnose problems when porting to new platforms.
However, it may also be able to better isolate user errors than just
using runtime checks. The assertions in the check routines spell
out in more detail the assumptions and invariants underlying the
algorithms. The checking is fairly extensive, and will slow down
execution noticeably. Calling malloc_stats or mallinfo with DEBUG
set will attempt to check every non-mmapped allocated and free chunk
in the course of computing the summaries.
 
ABORT_ON_ASSERT_FAILURE default: defined as 1 (true)
Debugging assertion failures can be nearly impossible if your
version of the assert macro causes malloc to be called, which will
lead to a cascade of further failures, blowing the runtime stack.
ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
which will usually make debugging easier.
 
MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32
The action to take before "return 0" when malloc fails to be able to
return memory because there is none available.
 
HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES
True if this system supports sbrk or an emulation of it.
 
MORECORE default: sbrk
The name of the sbrk-style system routine to call to obtain more
memory. See below for guidance on writing custom MORECORE
functions. The type of the argument to sbrk/MORECORE varies across
systems. It cannot be size_t, because it supports negative
arguments, so it is normally the signed type of the same width as
size_t (sometimes declared as "intptr_t"). It doesn't much matter
though. Internally, we only call it with arguments less than half
the max value of a size_t, which should work across all reasonable
possibilities, although sometimes generating compiler warnings. See
near the end of this file for guidelines for creating a custom
version of MORECORE.
 
MORECORE_CONTIGUOUS default: 1 (true)
If true, take advantage of fact that consecutive calls to MORECORE
with positive arguments always return contiguous increasing
addresses. This is true of unix sbrk. It does not hurt too much to
set it true anyway, since malloc copes with non-contiguities.
Setting it false when definitely non-contiguous saves time
and possibly wasted space it would take to discover this though.
 
MORECORE_CANNOT_TRIM default: NOT defined
True if MORECORE cannot release space back to the system when given
negative arguments. This is generally necessary only if you are
using a hand-crafted MORECORE function that cannot handle negative
arguments.
 
HAVE_MMAP default: 1 (true)
True if this system supports mmap or an emulation of it. If so, and
HAVE_MORECORE is not true, MMAP is used for all system
allocation. If set and HAVE_MORECORE is true as well, MMAP is
primarily used to directly allocate very large blocks. It is also
used as a backup strategy in cases where MORECORE fails to provide
space from system. Note: A single call to MUNMAP is assumed to be
able to unmap memory that may have be allocated using multiple calls
to MMAP, so long as they are adjacent.
 
HAVE_MREMAP default: 1 on linux, else 0
If true realloc() uses mremap() to re-allocate large blocks and
extend or shrink allocation spaces.
 
MMAP_CLEARS default: 1 on unix
True if mmap clears memory so calloc doesn't need to. This is true
for standard unix mmap using /dev/zero.
 
USE_BUILTIN_FFS default: 0 (i.e., not used)
Causes malloc to use the builtin ffs() function to compute indices.
Some compilers may recognize and intrinsify ffs to be faster than the
supplied C version. Also, the case of x86 using gcc is special-cased
to an asm instruction, so is already as fast as it can be, and so
this setting has no effect. (On most x86s, the asm version is only
slightly faster than the C version.)
 
malloc_getpagesize default: derive from system includes, or 4096.
The system page size. To the extent possible, this malloc manages
memory from the system in page-size units. This may be (and
usually is) a function rather than a constant. This is ignored
if WIN32, where page size is determined using getSystemInfo during
initialization.
 
USE_DEV_RANDOM default: 0 (i.e., not used)
Causes malloc to use /dev/random to initialize secure magic seed for
stamping footers. Otherwise, the current time is used.
 
NO_MALLINFO default: 0
If defined, don't compile "mallinfo". This can be a simple way
of dealing with mismatches between system declarations and
those in this file.
 
MALLINFO_FIELD_TYPE default: size_t
The type of the fields in the mallinfo struct. This was originally
defined as "int" in SVID etc, but is more usefully defined as
size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set
 
REALLOC_ZERO_BYTES_FREES default: not defined
This should be set if a call to realloc with zero bytes should
be the same as a call to free. Some people think it should. Otherwise,
since this malloc returns a unique pointer for malloc(0), so does
realloc(p, 0).
 
LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H
LACKS_STDLIB_H default: NOT defined unless on WIN32
Define these if your system does not have these header files.
You might need to manually insert some of the declarations they provide.
 
DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS,
system_info.dwAllocationGranularity in WIN32,
otherwise 64K.
Also settable using mallopt(M_GRANULARITY, x)
The unit for allocating and deallocating memory from the system. On
most systems with contiguous MORECORE, there is no reason to
make this more than a page. However, systems with MMAP tend to
either require or encourage larger granularities. You can increase
this value to prevent system allocation functions to be called so
often, especially if they are slow. The value must be at least one
page and must be a power of two. Setting to 0 causes initialization
to either page size or win32 region size. (Note: In previous
versions of malloc, the equivalent of this option was called
"TOP_PAD")
 
DEFAULT_TRIM_THRESHOLD default: 2MB
Also settable using mallopt(M_TRIM_THRESHOLD, x)
The maximum amount of unused top-most memory to keep before
releasing via malloc_trim in free(). Automatic trimming is mainly
useful in long-lived programs using contiguous MORECORE. Because
trimming via sbrk can be slow on some systems, and can sometimes be
wasteful (in cases where programs immediately afterward allocate
more large chunks) the value should be high enough so that your
overall system performance would improve by releasing this much
memory. As a rough guide, you might set to a value close to the
average size of a process (program) running on your system.
Releasing this much memory would allow such a process to run in
memory. Generally, it is worth tuning trim thresholds when a
program undergoes phases where several large chunks are allocated
and released in ways that can reuse each other's storage, perhaps
mixed with phases where there are no such chunks at all. The trim
value must be greater than page size to have any useful effect. To
disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
some people use of mallocing a huge space and then freeing it at
program startup, in an attempt to reserve system memory, doesn't
have the intended effect under automatic trimming, since that memory
will immediately be returned to the system.
 
DEFAULT_MMAP_THRESHOLD default: 256K
Also settable using mallopt(M_MMAP_THRESHOLD, x)
The request size threshold for using MMAP to directly service a
request. Requests of at least this size that cannot be allocated
using already-existing space will be serviced via mmap. (If enough
normal freed space already exists it is used instead.) Using mmap
segregates relatively large chunks of memory so that they can be
individually obtained and released from the host system. A request
serviced through mmap is never reused by any other request (at least
not directly; the system may just so happen to remap successive
requests to the same locations). Segregating space in this way has
the benefits that: Mmapped space can always be individually released
back to the system, which helps keep the system level memory demands
of a long-lived program low. Also, mapped memory doesn't become
`locked' between other chunks, as can happen with normally allocated
chunks, which means that even trimming via malloc_trim would not
release them. However, it has the disadvantage that the space
cannot be reclaimed, consolidated, and then used to service later
requests, as happens with normal chunks. The advantages of mmap
nearly always outweigh disadvantages for "large" chunks, but the
value of "large" may vary across systems. The default is an
empirically derived value that works well in most systems. You can
disable mmap by setting to MAX_SIZE_T.
 
*/
 
/** @addtogroup libcmalloc malloc
* @brief Malloc originally written by Doug Lea and ported to HelenOS.
* @ingroup libc
* @{
*/
/** @file
*/
 
 
#include <sys/types.h> /* For size_t */
 
/** Non-default helenos customizations */
#define LACKS_FCNTL_H
#define LACKS_SYS_MMAN_H
#define LACKS_SYS_PARAM_H
#undef HAVE_MMAP
#define HAVE_MMAP 0
#define LACKS_ERRNO_H
/* Set errno? */
#undef MALLOC_FAILURE_ACTION
#define MALLOC_FAILURE_ACTION
 
/* The maximum possible size_t value has all bits set */
#define MAX_SIZE_T (~(size_t)0)
 
#define ONLY_MSPACES 0
#define MSPACES 0
 
#ifdef MALLOC_ALIGNMENT_16
#define MALLOC_ALIGNMENT ((size_t)16U)
#else
#define MALLOC_ALIGNMENT ((size_t)8U)
#endif
 
#define FOOTERS 0
#define ABORT \
{ \
DEBUG("%s abort in %s on line %d\n", __FILE__, __func__, __LINE__); \
abort(); \
}
#define ABORT_ON_ASSERT_FAILURE 1
#define PROCEED_ON_ERROR 0
#define USE_LOCKS 1
#define INSECURE 0
#define HAVE_MMAP 0
 
#define MMAP_CLEARS 1
 
#define HAVE_MORECORE 1
#define MORECORE_CONTIGUOUS 1
#define MORECORE sbrk
#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */
 
#ifndef DEFAULT_TRIM_THRESHOLD
#ifndef MORECORE_CANNOT_TRIM
#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
#else /* MORECORE_CANNOT_TRIM */
#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
#endif /* MORECORE_CANNOT_TRIM */
#endif /* DEFAULT_TRIM_THRESHOLD */
#ifndef DEFAULT_MMAP_THRESHOLD
#if HAVE_MMAP
#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
#else /* HAVE_MMAP */
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
#endif /* HAVE_MMAP */
#endif /* DEFAULT_MMAP_THRESHOLD */
#ifndef USE_BUILTIN_FFS
#define USE_BUILTIN_FFS 0
#endif /* USE_BUILTIN_FFS */
#ifndef USE_DEV_RANDOM
#define USE_DEV_RANDOM 0
#endif /* USE_DEV_RANDOM */
#ifndef NO_MALLINFO
#define NO_MALLINFO 0
#endif /* NO_MALLINFO */
#ifndef MALLINFO_FIELD_TYPE
#define MALLINFO_FIELD_TYPE size_t
#endif /* MALLINFO_FIELD_TYPE */
 
/*
mallopt tuning options. SVID/XPG defines four standard parameter
numbers for mallopt, normally defined in malloc.h. None of these
are used in this malloc, so setting them has no effect. But this
malloc does support the following options.
*/
 
#define M_TRIM_THRESHOLD (-1)
#define M_GRANULARITY (-2)
#define M_MMAP_THRESHOLD (-3)
 
/*
========================================================================
To make a fully customizable malloc.h header file, cut everything
above this line, put into file malloc.h, edit to suit, and #include it
on the next line, as well as in programs that use this malloc.
========================================================================
*/
 
#include "malloc.h"
 
/*------------------------------ internal #includes ---------------------- */
 
#include <stdio.h> /* for printing in malloc_stats */
#include <string.h>
 
#ifndef LACKS_ERRNO_H
#include <errno.h> /* for MALLOC_FAILURE_ACTION */
#endif /* LACKS_ERRNO_H */
#if FOOTERS
#include <time.h> /* for magic initialization */
#endif /* FOOTERS */
#ifndef LACKS_STDLIB_H
#include <stdlib.h> /* for abort() */
#endif /* LACKS_STDLIB_H */
#ifdef DEBUG
#if ABORT_ON_ASSERT_FAILURE
#define assert(x) {if(!(x)) {DEBUG(#x);ABORT;}}
#else /* ABORT_ON_ASSERT_FAILURE */
#include <assert.h>
#endif /* ABORT_ON_ASSERT_FAILURE */
#else /* DEBUG */
#define assert(x)
#endif /* DEBUG */
#if USE_BUILTIN_FFS
#ifndef LACKS_STRINGS_H
#include <strings.h> /* for ffs */
#endif /* LACKS_STRINGS_H */
#endif /* USE_BUILTIN_FFS */
#if HAVE_MMAP
#ifndef LACKS_SYS_MMAN_H
#include <sys/mman.h> /* for mmap */
#endif /* LACKS_SYS_MMAN_H */
#ifndef LACKS_FCNTL_H
#include <fcntl.h>
#endif /* LACKS_FCNTL_H */
#endif /* HAVE_MMAP */
#if HAVE_MORECORE
#ifndef LACKS_UNISTD_H
#include <unistd.h> /* for sbrk */
#else /* LACKS_UNISTD_H */
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
extern void* sbrk(ptrdiff_t);
#endif /* FreeBSD etc */
#endif /* LACKS_UNISTD_H */
#endif /* HAVE_MMAP */
 
#ifndef WIN32
#ifndef malloc_getpagesize
# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
# ifndef _SC_PAGE_SIZE
# define _SC_PAGE_SIZE _SC_PAGESIZE
# endif
# endif
# ifdef _SC_PAGE_SIZE
# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
# else
# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
extern size_t getpagesize();
# define malloc_getpagesize getpagesize()
# else
# ifdef WIN32 /* use supplied emulation of getpagesize */
# define malloc_getpagesize getpagesize()
# else
# ifndef LACKS_SYS_PARAM_H
# include <sys/param.h>
# endif
# ifdef EXEC_PAGESIZE
# define malloc_getpagesize EXEC_PAGESIZE
# else
# ifdef NBPG
# ifndef CLSIZE
# define malloc_getpagesize NBPG
# else
# define malloc_getpagesize (NBPG * CLSIZE)
# endif
# else
# ifdef NBPC
# define malloc_getpagesize NBPC
# else
# ifdef PAGESIZE
# define malloc_getpagesize PAGESIZE
# else /* just guess */
# define malloc_getpagesize ((size_t)4096U)
# endif
# endif
# endif
# endif
# endif
# endif
# endif
#endif
#endif
 
/* ------------------- size_t and alignment properties -------------------- */
 
/* The byte and bit size of a size_t */
#define SIZE_T_SIZE (sizeof(size_t))
#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
 
/* Some constants coerced to size_t */
/* Annoying but necessary to avoid errors on some plaftorms */
#define SIZE_T_ZERO ((size_t)0)
#define SIZE_T_ONE ((size_t)1)
#define SIZE_T_TWO ((size_t)2)
#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
 
/* The bit mask value corresponding to MALLOC_ALIGNMENT */
#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
 
/* True if address a has acceptable alignment */
#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
 
/* the number of bytes to offset an address to align it */
#define align_offset(A)\
((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
 
/* -------------------------- MMAP preliminaries ------------------------- */
 
/*
If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
checks to fail so compiler optimizer can delete code rather than
using so many "#if"s.
*/
 
 
/* MORECORE and MMAP must return MFAIL on failure */
#define MFAIL ((void*)(MAX_SIZE_T))
#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */
 
#if !HAVE_MMAP
#define IS_MMAPPED_BIT (SIZE_T_ZERO)
#define USE_MMAP_BIT (SIZE_T_ZERO)
#define CALL_MMAP(s) MFAIL
#define CALL_MUNMAP(a, s) (-1)
#define DIRECT_MMAP(s) MFAIL
 
#else /* HAVE_MMAP */
#define IS_MMAPPED_BIT (SIZE_T_ONE)
#define USE_MMAP_BIT (SIZE_T_ONE)
 
#ifndef WIN32
#define CALL_MUNMAP(a, s) munmap((a), (s))
#define MMAP_PROT (PROT_READ|PROT_WRITE)
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif /* MAP_ANON */
#ifdef MAP_ANONYMOUS
#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
#else /* MAP_ANONYMOUS */
/*
Nearly all versions of mmap support MAP_ANONYMOUS, so the following
is unlikely to be needed, but is supplied just in case.
*/
#define MMAP_FLAGS (MAP_PRIVATE)
static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
(dev_zero_fd = open("/dev/zero", O_RDWR), \
mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
#endif /* MAP_ANONYMOUS */
 
#define DIRECT_MMAP(s) CALL_MMAP(s)
#else /* WIN32 */
 
/* Win32 MMAP via VirtualAlloc */
static void* win32mmap(size_t size) {
void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
return (ptr != 0)? ptr: MFAIL;
}
 
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
static void* win32direct_mmap(size_t size) {
void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
PAGE_READWRITE);
return (ptr != 0)? ptr: MFAIL;
}
 
/* This function supports releasing coalesed segments */
static int win32munmap(void* ptr, size_t size) {
MEMORY_BASIC_INFORMATION minfo;
char* cptr = ptr;
while (size) {
if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
return -1;
if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
minfo.State != MEM_COMMIT || minfo.RegionSize > size)
return -1;
if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
return -1;
cptr += minfo.RegionSize;
size -= minfo.RegionSize;
}
return 0;
}
 
#define CALL_MMAP(s) win32mmap(s)
#define CALL_MUNMAP(a, s) win32munmap((a), (s))
#define DIRECT_MMAP(s) win32direct_mmap(s)
#endif /* WIN32 */
#endif /* HAVE_MMAP */
 
#if HAVE_MMAP && HAVE_MREMAP
#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
#else /* HAVE_MMAP && HAVE_MREMAP */
#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
#endif /* HAVE_MMAP && HAVE_MREMAP */
 
#if HAVE_MORECORE
#define CALL_MORECORE(S) MORECORE(S)
#else /* HAVE_MORECORE */
#define CALL_MORECORE(S) MFAIL
#endif /* HAVE_MORECORE */
 
/* mstate bit set if continguous morecore disabled or failed */
#define USE_NONCONTIGUOUS_BIT (4U)
 
/* segment bit set in create_mspace_with_base */
#define EXTERN_BIT (8U)
 
 
/* --------------------------- Lock preliminaries ------------------------ */
 
#if USE_LOCKS
 
/*
When locks are defined, there are up to two global locks:
 
* If HAVE_MORECORE, morecore_mutex protects sequences of calls to
MORECORE. In many cases sys_alloc requires two calls, that should
not be interleaved with calls by other threads. This does not
protect against direct calls to MORECORE by other threads not
using this lock, so there is still code to cope the best we can on
interference.
 
* magic_init_mutex ensures that mparams.magic and other
unique mparams values are initialized only once.
*/
 
/* By default use posix locks */
#include <futex.h>
#define MLOCK_T atomic_t
#define INITIAL_LOCK(l) futex_initialize(l, 1)
/* futex_down cannot fail, but can return different
* retvals for OK
*/
#define ACQUIRE_LOCK(l) ({futex_down(l);0;})
#define RELEASE_LOCK(l) futex_up(l)
 
#if HAVE_MORECORE
static MLOCK_T morecore_mutex = FUTEX_INITIALIZER;
#endif /* HAVE_MORECORE */
 
static MLOCK_T magic_init_mutex = FUTEX_INITIALIZER;
 
 
#define USE_LOCK_BIT (2U)
#else /* USE_LOCKS */
#define USE_LOCK_BIT (0U)
#define INITIAL_LOCK(l)
#endif /* USE_LOCKS */
 
#if USE_LOCKS && HAVE_MORECORE
#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex);
#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex);
#else /* USE_LOCKS && HAVE_MORECORE */
#define ACQUIRE_MORECORE_LOCK()
#define RELEASE_MORECORE_LOCK()
#endif /* USE_LOCKS && HAVE_MORECORE */
 
#if USE_LOCKS
#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex);
#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex);
#else /* USE_LOCKS */
#define ACQUIRE_MAGIC_INIT_LOCK()
#define RELEASE_MAGIC_INIT_LOCK()
#endif /* USE_LOCKS */
 
 
/* ----------------------- Chunk representations ------------------------ */
 
/*
(The following includes lightly edited explanations by Colin Plumb.)
 
The malloc_chunk declaration below is misleading (but accurate and
necessary). It declares a "view" into memory allowing access to
necessary fields at known offsets from a given base.
 
Chunks of memory are maintained using a `boundary tag' method as
originally described by Knuth. (See the paper by Paul Wilson
ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
techniques.) Sizes of free chunks are stored both in the front of
each chunk and at the end. This makes consolidating fragmented
chunks into bigger chunks fast. The head fields also hold bits
representing whether chunks are free or in use.
 
Here are some pictures to make it clearer. They are "exploded" to
show that the state of a chunk can be thought of as extending from
the high 31 bits of the head field of its header through the
prev_foot and PINUSE_BIT bit of the following chunk header.
 
A chunk that's in use looks like:
 
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk (if P = 1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
| Size of this chunk 1| +-+
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+- -+
| |
+- -+
| :
+- size - sizeof(size_t) available payload bytes -+
: |
chunk-> +- -+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
| Size of next chunk (may or may not be in use) | +-+
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
And if it's free, it looks like this:
 
chunk-> +- -+
| User payload (must be in use, or we would have merged!) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
| Size of this chunk 0| +-+
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Prev pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :
+- size - sizeof(struct chunk) unused bytes -+
: |
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of this chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
| Size of next chunk (must be in use, or we would have merged)| +-+
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :
+- User payload -+
: |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|
+-+
Note that since we always merge adjacent free chunks, the chunks
adjacent to a free chunk must be in use.
 
Given a pointer to a chunk (which can be derived trivially from the
payload pointer) we can, in O(1) time, find out whether the adjacent
chunks are free, and if so, unlink them from the lists that they
are on and merge them with the current chunk.
 
Chunks always begin on even word boundaries, so the mem portion
(which is returned to the user) is also on an even word boundary, and
thus at least double-word aligned.
 
The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
chunk size (which is always a multiple of two words), is an in-use
bit for the *previous* chunk. If that bit is *clear*, then the
word before the current chunk size contains the previous chunk
size, and can be used to find the front of the previous chunk.
The very first chunk allocated always has this bit set, preventing
access to non-existent (or non-owned) memory. If pinuse is set for
any given chunk, then you CANNOT determine the size of the
previous chunk, and might even get a memory addressing fault when
trying to do so.
 
The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
the chunk size redundantly records whether the current chunk is
inuse. This redundancy enables usage checks within free and realloc,
and reduces indirection when freeing and consolidating chunks.
 
Each freshly allocated chunk must have both cinuse and pinuse set.
That is, each allocated chunk borders either a previously allocated
and still in-use chunk, or the base of its memory arena. This is
ensured by making all allocations from the the `lowest' part of any
found chunk. Further, no free chunk physically borders another one,
so each free chunk is known to be preceded and followed by either
inuse chunks or the ends of memory.
 
Note that the `foot' of the current chunk is actually represented
as the prev_foot of the NEXT chunk. This makes it easier to
deal with alignments etc but can be very confusing when trying
to extend or adapt this code.
 
The exceptions to all this are
 
1. The special chunk `top' is the top-most available chunk (i.e.,
the one bordering the end of available memory). It is treated
specially. Top is never included in any bin, is used only if
no other chunk is available, and is released back to the
system if it is very large (see M_TRIM_THRESHOLD). In effect,
the top chunk is treated as larger (and thus less well
fitting) than any other available chunk. The top chunk
doesn't update its trailing size field since there is no next
contiguous chunk that would have to index off it. However,
space is still allocated for it (TOP_FOOT_SIZE) to enable
separation or merging when space is extended.
 
3. Chunks allocated via mmap, which have the lowest-order bit
(IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
PINUSE_BIT in their head fields. Because they are allocated
one-by-one, each must carry its own prev_foot field, which is
also used to hold the offset this chunk has within its mmapped
region, which is needed to preserve alignment. Each mmapped
chunk is trailed by the first two fields of a fake next-chunk
for sake of usage checks.
 
*/
 
struct malloc_chunk {
size_t prev_foot; /* Size of previous chunk (if free). */
size_t head; /* Size and inuse bits. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
};
 
typedef struct malloc_chunk mchunk;
typedef struct malloc_chunk* mchunkptr;
typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
typedef unsigned int bindex_t; /* Described below */
typedef unsigned int binmap_t; /* Described below */
typedef unsigned int flag_t; /* The type of various bit flag sets */
 
/* ------------------- Chunks sizes and alignments ----------------------- */
 
#define MCHUNK_SIZE (sizeof(mchunk))
 
#if FOOTERS
#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
#else /* FOOTERS */
#define CHUNK_OVERHEAD (SIZE_T_SIZE)
#endif /* FOOTERS */
 
/* MMapped chunks need a second word of overhead ... */
#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
/* ... and additional padding for fake next-chunk at foot */
#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
 
/* The smallest size we can malloc is an aligned minimal chunk */
#define MIN_CHUNK_SIZE\
((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
 
/* conversion from malloc headers to user pointers, and back */
#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
/* chunk associated with aligned address A */
#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
 
/* Bounds on request (not chunk) sizes. */
#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
 
/* pad request bytes into a usable size */
#define pad_request(req) \
(((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
 
/* pad request, checking for minimum (but not maximum) */
#define request2size(req) \
(((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
 
 
/* ------------------ Operations on head and foot fields ----------------- */
 
/*
The head field of a chunk is or'ed with PINUSE_BIT when previous
adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
use. If the chunk was obtained with mmap, the prev_foot field has
IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
mmapped region to the base of the chunk.
*/
 
#define PINUSE_BIT (SIZE_T_ONE)
#define CINUSE_BIT (SIZE_T_TWO)
#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
 
/* Head value for fenceposts */
#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
 
/* extraction of fields from head words */
#define cinuse(p) ((p)->head & CINUSE_BIT)
#define pinuse(p) ((p)->head & PINUSE_BIT)
#define chunksize(p) ((p)->head & ~(INUSE_BITS))
 
#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT)
 
/* Treat space at ptr +/- offset as a chunk */
#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
 
/* Ptr to next or previous physical malloc_chunk. */
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
 
/* extract next chunk's pinuse bit */
#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
 
/* Get/set size at footer */
#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
 
/* Set size, pinuse bit, and foot */
#define set_size_and_pinuse_of_free_chunk(p, s)\
((p)->head = (s|PINUSE_BIT), set_foot(p, s))
 
/* Set size, pinuse bit, foot, and clear next pinuse */
#define set_free_with_pinuse(p, s, n)\
(clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
 
#define is_mmapped(p)\
(!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
 
/* Get the internal overhead associated with chunk p */
#define overhead_for(p)\
(is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
 
/* Return true if malloced space is not necessarily cleared */
#if MMAP_CLEARS
#define calloc_must_clear(p) (!is_mmapped(p))
#else /* MMAP_CLEARS */
#define calloc_must_clear(p) (1)
#endif /* MMAP_CLEARS */
 
/* ---------------------- Overlaid data structures ----------------------- */
 
/*
When chunks are not in use, they are treated as nodes of either
lists or trees.
 
"Small" chunks are stored in circular doubly-linked lists, and look
like this:
 
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' | Size of chunk, in bytes |P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Forward pointer to next chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Back pointer to previous chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused space (may be 0 bytes long) .
. .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:' | Size of chunk, in bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
Larger chunks are kept in a form of bitwise digital trees (aka
tries) keyed on chunksizes. Because malloc_tree_chunks are only for
free chunks greater than 256 bytes, their size doesn't impose any
constraints on user chunk sizes. Each node looks like:
 
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' | Size of chunk, in bytes |P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Forward pointer to next chunk of same size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Back pointer to previous chunk of same size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pointer to left child (child[0]) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pointer to right child (child[1]) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pointer to parent |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| bin index of this chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused space .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:' | Size of chunk, in bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
Each tree holding treenodes is a tree of unique chunk sizes. Chunks
of the same size are arranged in a circularly-linked list, with only
the oldest chunk (the next to be used, in our FIFO ordering)
actually in the tree. (Tree members are distinguished by a non-null
parent pointer.) If a chunk with the same size an an existing node
is inserted, it is linked off the existing node using pointers that
work in the same way as fd/bk pointers of small chunks.
 
Each tree contains a power of 2 sized range of chunk sizes (the
smallest is 0x100 <= x < 0x180), which is is divided in half at each
tree level, with the chunks in the smaller half of the range (0x100
<= x < 0x140 for the top nose) in the left subtree and the larger
half (0x140 <= x < 0x180) in the right subtree. This is, of course,
done by inspecting individual bits.
 
Using these rules, each node's left subtree contains all smaller
sizes than its right subtree. However, the node at the root of each
subtree has no particular ordering relationship to either. (The
dividing line between the subtree sizes is based on trie relation.)
If we remove the last chunk of a given size from the interior of the
tree, we need to replace it with a leaf node. The tree ordering
rules permit a node to be replaced by any leaf below it.
 
The smallest chunk in a tree (a common operation in a best-fit
allocator) can be found by walking a path to the leftmost leaf in
the tree. Unlike a usual binary tree, where we follow left child
pointers until we reach a null, here we follow the right child
pointer any time the left one is null, until we reach a leaf with
both child pointers null. The smallest chunk in the tree will be
somewhere along that path.
 
The worst case number of steps to add, find, or remove a node is
bounded by the number of bits differentiating chunks within
bins. Under current bin calculations, this ranges from 6 up to 21
(for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
is of course much better.
*/
 
struct malloc_tree_chunk {
/* The first four fields must be compatible with malloc_chunk */
size_t prev_foot;
size_t head;
struct malloc_tree_chunk* fd;
struct malloc_tree_chunk* bk;
 
struct malloc_tree_chunk* child[2];
struct malloc_tree_chunk* parent;
bindex_t index;
};
 
typedef struct malloc_tree_chunk tchunk;
typedef struct malloc_tree_chunk* tchunkptr;
typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
 
/* A little helper macro for trees */
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
 
/* ----------------------------- Segments -------------------------------- */
 
/*
Each malloc space may include non-contiguous segments, held in a
list headed by an embedded malloc_segment record representing the
top-most space. Segments also include flags holding properties of
the space. Large chunks that are directly allocated by mmap are not
included in this list. They are instead independently created and
destroyed without otherwise keeping track of them.
 
Segment management mainly comes into play for spaces allocated by
MMAP. Any call to MMAP might or might not return memory that is
adjacent to an existing segment. MORECORE normally contiguously
extends the current space, so this space is almost always adjacent,
which is simpler and faster to deal with. (This is why MORECORE is
used preferentially to MMAP when both are available -- see
sys_alloc.) When allocating using MMAP, we don't use any of the
hinting mechanisms (inconsistently) supported in various
implementations of unix mmap, or distinguish reserving from
committing memory. Instead, we just ask for space, and exploit
contiguity when we get it. It is probably possible to do
better than this on some systems, but no general scheme seems
to be significantly better.
 
Management entails a simpler variant of the consolidation scheme
used for chunks to reduce fragmentation -- new adjacent memory is
normally prepended or appended to an existing segment. However,
there are limitations compared to chunk consolidation that mostly
reflect the fact that segment processing is relatively infrequent
(occurring only when getting memory from system) and that we
don't expect to have huge numbers of segments:
 
* Segments are not indexed, so traversal requires linear scans. (It
would be possible to index these, but is not worth the extra
overhead and complexity for most programs on most platforms.)
* New segments are only appended to old ones when holding top-most
memory; if they cannot be prepended to others, they are held in
different segments.
 
Except for the top-most segment of an mstate, each segment record
is kept at the tail of its segment. Segments are added by pushing
segment records onto the list headed by &mstate.seg for the
containing mstate.
 
Segment flags control allocation/merge/deallocation policies:
* If EXTERN_BIT set, then we did not allocate this segment,
and so should not try to deallocate or merge with others.
(This currently holds only for the initial segment passed
into create_mspace_with_base.)
* If IS_MMAPPED_BIT set, the segment may be merged with
other surrounding mmapped segments and trimmed/de-allocated
using munmap.
* If neither bit is set, then the segment was obtained using
MORECORE so can be merged with surrounding MORECORE'd segments
and deallocated/trimmed using MORECORE with negative arguments.
*/
 
struct malloc_segment {
char* base; /* base address */
size_t size; /* allocated size */
struct malloc_segment* next; /* ptr to next segment */
flag_t sflags; /* mmap and extern flag */
};
 
#define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT)
#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
 
typedef struct malloc_segment msegment;
typedef struct malloc_segment* msegmentptr;
 
/* ---------------------------- malloc_state ----------------------------- */
 
/*
A malloc_state holds all of the bookkeeping for a space.
The main fields are:
 
Top
The topmost chunk of the currently active segment. Its size is
cached in topsize. The actual size of topmost space is
topsize+TOP_FOOT_SIZE, which includes space reserved for adding
fenceposts and segment records if necessary when getting more
space from the system. The size at which to autotrim top is
cached from mparams in trim_check, except that it is disabled if
an autotrim fails.
 
Designated victim (dv)
This is the preferred chunk for servicing small requests that
don't have exact fits. It is normally the chunk split off most
recently to service another small request. Its size is cached in
dvsize. The link fields of this chunk are not maintained since it
is not kept in a bin.
 
SmallBins
An array of bin headers for free chunks. These bins hold chunks
with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
chunks of all the same size, spaced 8 bytes apart. To simplify
use in double-linked lists, each bin header acts as a malloc_chunk
pointing to the real first node, if it exists (else pointing to
itself). This avoids special-casing for headers. But to avoid
waste, we allocate only the fd/bk pointers of bins, and then use
repositioning tricks to treat these as the fields of a chunk.
 
TreeBins
Treebins are pointers to the roots of trees holding a range of
sizes. There are 2 equally spaced treebins for each power of two
from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
larger.
 
Bin maps
There is one bit map for small bins ("smallmap") and one for
treebins ("treemap). Each bin sets its bit when non-empty, and
clears the bit when empty. Bit operations are then used to avoid
bin-by-bin searching -- nearly all "search" is done without ever
looking at bins that won't be selected. The bit maps
conservatively use 32 bits per map word, even if on 64bit system.
For a good description of some of the bit-based techniques used
here, see Henry S. Warren Jr's book "Hacker's Delight" (and
supplement at http://hackersdelight.org/). Many of these are
intended to reduce the branchiness of paths through malloc etc, as
well as to reduce the number of memory locations read or written.
 
Segments
A list of segments headed by an embedded malloc_segment record
representing the initial space.
 
Address check support
The least_addr field is the least address ever obtained from
MORECORE or MMAP. Attempted frees and reallocs of any address less
than this are trapped (unless INSECURE is defined).
 
Magic tag
A cross-check field that should always hold same value as mparams.magic.
 
Flags
Bits recording whether to use MMAP, locks, or contiguous MORECORE
 
Statistics
Each space keeps track of current and maximum system memory
obtained via MORECORE or MMAP.
 
Locking
If USE_LOCKS is defined, the "mutex" lock is acquired and released
around every public call using this mspace.
*/
 
/* Bin types, widths and sizes */
#define NSMALLBINS (32U)
#define NTREEBINS (32U)
#define SMALLBIN_SHIFT (3U)
#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
#define TREEBIN_SHIFT (8U)
#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
 
struct malloc_state {
binmap_t smallmap;
binmap_t treemap;
size_t dvsize;
size_t topsize;
char* least_addr;
mchunkptr dv;
mchunkptr top;
size_t trim_check;
size_t magic;
mchunkptr smallbins[(NSMALLBINS+1)*2];
tbinptr treebins[NTREEBINS];
size_t footprint;
size_t max_footprint;
flag_t mflags;
#if USE_LOCKS
MLOCK_T mutex; /* locate lock among fields that rarely change */
#endif /* USE_LOCKS */
msegment seg;
};
 
typedef struct malloc_state* mstate;
 
/* ------------- Global malloc_state and malloc_params ------------------- */
 
/*
malloc_params holds global properties, including those that can be
dynamically set using mallopt. There is a single instance, mparams,
initialized in init_mparams.
*/
 
struct malloc_params {
size_t magic;
size_t page_size;
size_t granularity;
size_t mmap_threshold;
size_t trim_threshold;
flag_t default_mflags;
};
 
static struct malloc_params mparams;
 
/* The global malloc_state used for all non-"mspace" calls */
static struct malloc_state _gm_;
#define gm (&_gm_)
#define is_global(M) ((M) == &_gm_)
#define is_initialized(M) ((M)->top != 0)
 
/* -------------------------- system alloc setup ------------------------- */
 
/* Operations on mflags */
 
#define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
 
#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
 
#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
 
#define set_lock(M,L)\
((M)->mflags = (L)?\
((M)->mflags | USE_LOCK_BIT) :\
((M)->mflags & ~USE_LOCK_BIT))
 
/* page-align a size */
#define page_align(S)\
(((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
 
/* granularity-align a size */
#define granularity_align(S)\
(((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
 
#define is_page_aligned(S)\
(((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
#define is_granularity_aligned(S)\
(((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
 
/* True if segment S holds address A */
#define segment_holds(S, A)\
((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
 
/* Return segment holding given address */
static msegmentptr segment_holding(mstate m, char* addr) {
msegmentptr sp = &m->seg;
for (;;) {
if (addr >= sp->base && addr < sp->base + sp->size)
return sp;
if ((sp = sp->next) == 0)
return 0;
}
}
 
/* Return true if segment contains a segment link */
static int has_segment_link(mstate m, msegmentptr ss) {
msegmentptr sp = &m->seg;
for (;;) {
if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
return 1;
if ((sp = sp->next) == 0)
return 0;
}
}
 
#ifndef MORECORE_CANNOT_TRIM
#define should_trim(M,s) ((s) > (M)->trim_check)
#else /* MORECORE_CANNOT_TRIM */
#define should_trim(M,s) (0)
#endif /* MORECORE_CANNOT_TRIM */
 
/*
TOP_FOOT_SIZE is padding at the end of a segment, including space
that may be needed to place segment records and fenceposts when new
noncontiguous segments are added.
*/
#define TOP_FOOT_SIZE\
(align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
 
 
/* ------------------------------- Hooks -------------------------------- */
 
/*
PREACTION should be defined to return 0 on success, and nonzero on
failure. If you are not using locking, you can redefine these to do
anything you like.
*/
 
#if USE_LOCKS
 
/* Ensure locks are initialized */
#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
 
#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
#else /* USE_LOCKS */
 
#ifndef PREACTION
#define PREACTION(M) (0)
#endif /* PREACTION */
 
#ifndef POSTACTION
#define POSTACTION(M)
#endif /* POSTACTION */
 
#endif /* USE_LOCKS */
 
/*
CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
USAGE_ERROR_ACTION is triggered on detected bad frees and
reallocs. The argument p is an address that might have triggered the
fault. It is ignored by the two predefined actions, but might be
useful in custom actions that try to help diagnose errors.
*/
 
#if PROCEED_ON_ERROR
 
/* A count of the number of corruption errors causing resets */
int malloc_corruption_error_count;
 
/* default corruption action */
static void reset_on_error(mstate m);
 
#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
#define USAGE_ERROR_ACTION(m, p)
 
#else /* PROCEED_ON_ERROR */
 
#ifndef CORRUPTION_ERROR_ACTION
#define CORRUPTION_ERROR_ACTION(m) ABORT
#endif /* CORRUPTION_ERROR_ACTION */
 
#ifndef USAGE_ERROR_ACTION
#define USAGE_ERROR_ACTION(m,p) ABORT
#endif /* USAGE_ERROR_ACTION */
 
#endif /* PROCEED_ON_ERROR */
 
/* -------------------------- Debugging setup ---------------------------- */
 
#if ! DEBUG
 
#define check_free_chunk(M,P)
#define check_inuse_chunk(M,P)
#define check_malloced_chunk(M,P,N)
#define check_mmapped_chunk(M,P)
#define check_malloc_state(M)
#define check_top_chunk(M,P)
 
#else /* DEBUG */
#define check_free_chunk(M,P) do_check_free_chunk(M,P)
#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
#define check_top_chunk(M,P) do_check_top_chunk(M,P)
#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
#define check_malloc_state(M) do_check_malloc_state(M)
 
static void do_check_any_chunk(mstate m, mchunkptr p);
static void do_check_top_chunk(mstate m, mchunkptr p);
static void do_check_mmapped_chunk(mstate m, mchunkptr p);
static void do_check_inuse_chunk(mstate m, mchunkptr p);
static void do_check_free_chunk(mstate m, mchunkptr p);
static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
static void do_check_tree(mstate m, tchunkptr t);
static void do_check_treebin(mstate m, bindex_t i);
static void do_check_smallbin(mstate m, bindex_t i);
static void do_check_malloc_state(mstate m);
static int bin_find(mstate m, mchunkptr x);
static size_t traverse_and_check(mstate m);
#endif /* DEBUG */
 
/* ---------------------------- Indexing Bins ---------------------------- */
 
#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
#define small_index(s) ((s) >> SMALLBIN_SHIFT)
#define small_index2size(i) ((i) << SMALLBIN_SHIFT)
#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
 
/* addressing by index. See above about smallbin repositioning */
#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
#define treebin_at(M,i) (&((M)->treebins[i]))
 
/* assign tree index for size S to variable I */
#if defined(__GNUC__) && defined(i386)
#define compute_tree_index(S, I)\
{\
size_t X = S >> TREEBIN_SHIFT;\
if (X == 0)\
I = 0;\
else if (X > 0xFFFF)\
I = NTREEBINS-1;\
else {\
unsigned int K;\
asm("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\
I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
}\
}
#else /* GNUC */
#define compute_tree_index(S, I)\
{\
size_t X = S >> TREEBIN_SHIFT;\
if (X == 0)\
I = 0;\
else if (X > 0xFFFF)\
I = NTREEBINS-1;\
else {\
unsigned int Y = (unsigned int)X;\
unsigned int N = ((Y - 0x100) >> 16) & 8;\
unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
N += K;\
N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
K = 14 - N + ((Y <<= K) >> 15);\
I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
}\
}
#endif /* GNUC */
 
/* Bit representing maximum resolved size in a treebin at i */
#define bit_for_tree_index(i) \
(i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
 
/* Shift placing maximum resolved bit in a treebin at i as sign bit */
#define leftshift_for_tree_index(i) \
((i == NTREEBINS-1)? 0 : \
((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
 
/* The size of the smallest chunk held in bin with index i */
#define minsize_for_tree_index(i) \
((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
(((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
 
 
/* ------------------------ Operations on bin maps ----------------------- */
 
/* bit corresponding to given index */
#define idx2bit(i) ((binmap_t)(1) << (i))
 
/* Mark/Clear bits with given index */
#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
 
#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
 
/* index corresponding to given bit */
 
#if defined(__GNUC__) && defined(i386)
#define compute_bit2idx(X, I)\
{\
unsigned int J;\
asm("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
I = (bindex_t)J;\
}
 
#else /* GNUC */
#if USE_BUILTIN_FFS
#define compute_bit2idx(X, I) I = ffs(X)-1
 
#else /* USE_BUILTIN_FFS */
#define compute_bit2idx(X, I)\
{\
unsigned int Y = X - 1;\
unsigned int K = Y >> (16-4) & 16;\
unsigned int N = K; Y >>= K;\
N += K = Y >> (8-3) & 8; Y >>= K;\
N += K = Y >> (4-2) & 4; Y >>= K;\
N += K = Y >> (2-1) & 2; Y >>= K;\
N += K = Y >> (1-0) & 1; Y >>= K;\
I = (bindex_t)(N + Y);\
}
#endif /* USE_BUILTIN_FFS */
#endif /* GNUC */
 
/* isolate the least set bit of a bitmap */
#define least_bit(x) ((x) & -(x))
 
/* mask with all bits to left of least bit of x on */
#define left_bits(x) ((x<<1) | -(x<<1))
 
/* mask with all bits to left of or equal to least bit of x on */
#define same_or_left_bits(x) ((x) | -(x))
 
 
/* ----------------------- Runtime Check Support ------------------------- */
 
/*
For security, the main invariant is that malloc/free/etc never
writes to a static address other than malloc_state, unless static
malloc_state itself has been corrupted, which cannot occur via
malloc (because of these checks). In essence this means that we
believe all pointers, sizes, maps etc held in malloc_state, but
check all of those linked or offsetted from other embedded data
structures. These checks are interspersed with main code in a way
that tends to minimize their run-time cost.
 
When FOOTERS is defined, in addition to range checking, we also
verify footer fields of inuse chunks, which can be used guarantee
that the mstate controlling malloc/free is intact. This is a
streamlined version of the approach described by William Robertson
et al in "Run-time Detection of Heap-based Overflows" LISA'03
http://www.usenix.org/events/lisa03/tech/robertson.html The footer
of an inuse chunk holds the xor of its mstate and a random seed,
that is checked upon calls to free() and realloc(). This is
(probablistically) unguessable from outside the program, but can be
computed by any code successfully malloc'ing any chunk, so does not
itself provide protection against code that has already broken
security through some other means. Unlike Robertson et al, we
always dynamically check addresses of all offset chunks (previous,
next, etc). This turns out to be cheaper than relying on hashes.
*/
 
#if !INSECURE
/* Check if address a is at least as high as any from MORECORE or MMAP */
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
/* Check if address of next chunk n is higher than base chunk p */
#define ok_next(p, n) ((char*)(p) < (char*)(n))
/* Check if p has its cinuse bit on */
#define ok_cinuse(p) cinuse(p)
/* Check if p has its pinuse bit on */
#define ok_pinuse(p) pinuse(p)
 
#else /* !INSECURE */
#define ok_address(M, a) (1)
#define ok_next(b, n) (1)
#define ok_cinuse(p) (1)
#define ok_pinuse(p) (1)
#endif /* !INSECURE */
 
#if (FOOTERS && !INSECURE)
/* Check if (alleged) mstate m has expected magic field */
#define ok_magic(M) ((M)->magic == mparams.magic)
#else /* (FOOTERS && !INSECURE) */
#define ok_magic(M) (1)
#endif /* (FOOTERS && !INSECURE) */
 
 
/* In gcc, use __builtin_expect to minimize impact of checks */
#if !INSECURE
#if defined(__GNUC__) && __GNUC__ >= 3
#define RTCHECK(e) __builtin_expect(e, 1)
#else /* GNUC */
#define RTCHECK(e) (e)
#endif /* GNUC */
#else /* !INSECURE */
#define RTCHECK(e) (1)
#endif /* !INSECURE */
 
/* macros to set up inuse chunks with or without footers */
 
#if !FOOTERS
 
#define mark_inuse_foot(M,p,s)
 
/* Set cinuse bit and pinuse bit of next chunk */
#define set_inuse(M,p,s)\
((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
 
/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
#define set_inuse_and_pinuse(M,p,s)\
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
 
/* Set size, cinuse and pinuse bit of this chunk */
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
 
#else /* FOOTERS */
 
/* Set foot of inuse chunk to be xor of mstate and seed */
#define mark_inuse_foot(M,p,s)\
(((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
 
#define get_mstate_for(p)\
((mstate)(((mchunkptr)((char*)(p) +\
(chunksize(p))))->prev_foot ^ mparams.magic))
 
#define set_inuse(M,p,s)\
((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
(((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
mark_inuse_foot(M,p,s))
 
#define set_inuse_and_pinuse(M,p,s)\
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
(((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
mark_inuse_foot(M,p,s))
 
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
mark_inuse_foot(M, p, s))
 
#endif /* !FOOTERS */
 
/* ---------------------------- setting mparams -------------------------- */
 
/* Initialize mparams */
static int init_mparams(void) {
if (mparams.page_size == 0) {
size_t s;
 
mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
#if MORECORE_CONTIGUOUS
mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
#else /* MORECORE_CONTIGUOUS */
mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
#endif /* MORECORE_CONTIGUOUS */
 
#if (FOOTERS && !INSECURE)
{
#if USE_DEV_RANDOM
int fd;
unsigned char buf[sizeof(size_t)];
/* Try to use /dev/urandom, else fall back on using time */
if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
read(fd, buf, sizeof(buf)) == sizeof(buf)) {
s = *((size_t *) buf);
close(fd);
}
else
#endif /* USE_DEV_RANDOM */
s = (size_t)(time(0) ^ (size_t)0x55555555U);
 
s |= (size_t)8U; /* ensure nonzero */
s &= ~(size_t)7U; /* improve chances of fault for bad values */
 
}
#else /* (FOOTERS && !INSECURE) */
s = (size_t)0x58585858U;
#endif /* (FOOTERS && !INSECURE) */
ACQUIRE_MAGIC_INIT_LOCK();
if (mparams.magic == 0) {
mparams.magic = s;
/* Set up lock for main malloc area */
INITIAL_LOCK(&gm->mutex);
gm->mflags = mparams.default_mflags;
}
RELEASE_MAGIC_INIT_LOCK();
 
#ifndef WIN32
mparams.page_size = malloc_getpagesize;
mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
DEFAULT_GRANULARITY : mparams.page_size);
#else /* WIN32 */
{
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
mparams.page_size = system_info.dwPageSize;
mparams.granularity = system_info.dwAllocationGranularity;
}
#endif /* WIN32 */
 
/* Sanity-check configuration:
size_t must be unsigned and as wide as pointer type.
ints must be at least 4 bytes.
alignment must be at least 8.
Alignment, min chunk size, and page size must all be powers of 2.
*/
if ((sizeof(size_t) != sizeof(char*)) ||
(MAX_SIZE_T < MIN_CHUNK_SIZE) ||
(sizeof(int) < 4) ||
(MALLOC_ALIGNMENT < (size_t)8U) ||
((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0))
ABORT;
}
return 0;
}
 
/* support for mallopt */
static int change_mparam(int param_number, int value) {
size_t val = (size_t)value;
init_mparams();
switch(param_number) {
case M_TRIM_THRESHOLD:
mparams.trim_threshold = val;
return 1;
case M_GRANULARITY:
if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
mparams.granularity = val;
return 1;
}
else
return 0;
case M_MMAP_THRESHOLD:
mparams.mmap_threshold = val;
return 1;
default:
return 0;
}
}
 
#if DEBUG
/* ------------------------- Debugging Support --------------------------- */
 
/* Check properties of any chunk, whether free, inuse, mmapped etc */
static void do_check_any_chunk(mstate m, mchunkptr p) {
assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
assert(ok_address(m, p));
}
 
/* Check properties of top chunk */
static void do_check_top_chunk(mstate m, mchunkptr p) {
msegmentptr sp = segment_holding(m, (char*)p);
size_t sz = chunksize(p);
assert(sp != 0);
assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
assert(ok_address(m, p));
assert(sz == m->topsize);
assert(sz > 0);
assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
assert(pinuse(p));
assert(!next_pinuse(p));
}
 
/* Check properties of (inuse) mmapped chunks */
static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
size_t sz = chunksize(p);
size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
assert(is_mmapped(p));
assert(use_mmap(m));
assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
assert(ok_address(m, p));
assert(!is_small(sz));
assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
}
 
/* Check properties of inuse chunks */
static void do_check_inuse_chunk(mstate m, mchunkptr p) {
do_check_any_chunk(m, p);
assert(cinuse(p));
assert(next_pinuse(p));
/* If not pinuse and not mmapped, previous chunk has OK offset */
assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
if (is_mmapped(p))
do_check_mmapped_chunk(m, p);
}
 
/* Check properties of free chunks */
static void do_check_free_chunk(mstate m, mchunkptr p) {
size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
mchunkptr next = chunk_plus_offset(p, sz);
do_check_any_chunk(m, p);
assert(!cinuse(p));
assert(!next_pinuse(p));
assert (!is_mmapped(p));
if (p != m->dv && p != m->top) {
if (sz >= MIN_CHUNK_SIZE) {
assert((sz & CHUNK_ALIGN_MASK) == 0);
assert(is_aligned(chunk2mem(p)));
assert(next->prev_foot == sz);
assert(pinuse(p));
assert (next == m->top || cinuse(next));
assert(p->fd->bk == p);
assert(p->bk->fd == p);
}
else /* markers are always of size SIZE_T_SIZE */
assert(sz == SIZE_T_SIZE);
}
}
 
/* Check properties of malloced chunks at the point they are malloced */
static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
if (mem != 0) {
mchunkptr p = mem2chunk(mem);
size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
do_check_inuse_chunk(m, p);
assert((sz & CHUNK_ALIGN_MASK) == 0);
assert(sz >= MIN_CHUNK_SIZE);
assert(sz >= s);
/* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
}
}
 
/* Check a tree and its subtrees. */
static void do_check_tree(mstate m, tchunkptr t) {
tchunkptr head = 0;
tchunkptr u = t;
bindex_t tindex = t->index;
size_t tsize = chunksize(t);
bindex_t idx;
compute_tree_index(tsize, idx);
assert(tindex == idx);
assert(tsize >= MIN_LARGE_SIZE);
assert(tsize >= minsize_for_tree_index(idx));
assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
 
do { /* traverse through chain of same-sized nodes */
do_check_any_chunk(m, ((mchunkptr)u));
assert(u->index == tindex);
assert(chunksize(u) == tsize);
assert(!cinuse(u));
assert(!next_pinuse(u));
assert(u->fd->bk == u);
assert(u->bk->fd == u);
if (u->parent == 0) {
assert(u->child[0] == 0);
assert(u->child[1] == 0);
}
else {
assert(head == 0); /* only one node on chain has parent */
head = u;
assert(u->parent != u);
assert (u->parent->child[0] == u ||
u->parent->child[1] == u ||
*((tbinptr*)(u->parent)) == u);
if (u->child[0] != 0) {
assert(u->child[0]->parent == u);
assert(u->child[0] != u);
do_check_tree(m, u->child[0]);
}
if (u->child[1] != 0) {
assert(u->child[1]->parent == u);
assert(u->child[1] != u);
do_check_tree(m, u->child[1]);
}
if (u->child[0] != 0 && u->child[1] != 0) {
assert(chunksize(u->child[0]) < chunksize(u->child[1]));
}
}
u = u->fd;
} while (u != t);
assert(head != 0);
}
 
/* Check all the chunks in a treebin. */
static void do_check_treebin(mstate m, bindex_t i) {
tbinptr* tb = treebin_at(m, i);
tchunkptr t = *tb;
int empty = (m->treemap & (1U << i)) == 0;
if (t == 0)
assert(empty);
if (!empty)
do_check_tree(m, t);
}
 
/* Check all the chunks in a smallbin. */
static void do_check_smallbin(mstate m, bindex_t i) {
sbinptr b = smallbin_at(m, i);
mchunkptr p = b->bk;
unsigned int empty = (m->smallmap & (1U << i)) == 0;
if (p == b)
assert(empty);
if (!empty) {
for (; p != b; p = p->bk) {
size_t size = chunksize(p);
mchunkptr q;
/* each chunk claims to be free */
do_check_free_chunk(m, p);
/* chunk belongs in bin */
assert(small_index(size) == i);
assert(p->bk == b || chunksize(p->bk) == chunksize(p));
/* chunk is followed by an inuse chunk */
q = next_chunk(p);
if (q->head != FENCEPOST_HEAD)
do_check_inuse_chunk(m, q);
}
}
}
 
/* Find x in a bin. Used in other check functions. */
static int bin_find(mstate m, mchunkptr x) {
size_t size = chunksize(x);
if (is_small(size)) {
bindex_t sidx = small_index(size);
sbinptr b = smallbin_at(m, sidx);
if (smallmap_is_marked(m, sidx)) {
mchunkptr p = b;
do {
if (p == x)
return 1;
} while ((p = p->fd) != b);
}
}
else {
bindex_t tidx;
compute_tree_index(size, tidx);
if (treemap_is_marked(m, tidx)) {
tchunkptr t = *treebin_at(m, tidx);
size_t sizebits = size << leftshift_for_tree_index(tidx);
while (t != 0 && chunksize(t) != size) {
t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
sizebits <<= 1;
}
if (t != 0) {
tchunkptr u = t;
do {
if (u == (tchunkptr)x)
return 1;
} while ((u = u->fd) != t);
}
}
}
return 0;
}
 
/* Traverse each chunk and check it; return total */
static size_t traverse_and_check(mstate m) {
size_t sum = 0;
if (is_initialized(m)) {
msegmentptr s = &m->seg;
sum += m->topsize + TOP_FOOT_SIZE;
while (s != 0) {
mchunkptr q = align_as_chunk(s->base);
mchunkptr lastq = 0;
assert(pinuse(q));
while (segment_holds(s, q) &&
q != m->top && q->head != FENCEPOST_HEAD) {
sum += chunksize(q);
if (cinuse(q)) {
assert(!bin_find(m, q));
do_check_inuse_chunk(m, q);
}
else {
assert(q == m->dv || bin_find(m, q));
assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
do_check_free_chunk(m, q);
}
lastq = q;
q = next_chunk(q);
}
s = s->next;
}
}
return sum;
}
 
/* Check all properties of malloc_state. */
static void do_check_malloc_state(mstate m) {
bindex_t i;
size_t total;
/* check bins */
for (i = 0; i < NSMALLBINS; ++i)
do_check_smallbin(m, i);
for (i = 0; i < NTREEBINS; ++i)
do_check_treebin(m, i);
 
if (m->dvsize != 0) { /* check dv chunk */
do_check_any_chunk(m, m->dv);
assert(m->dvsize == chunksize(m->dv));
assert(m->dvsize >= MIN_CHUNK_SIZE);
assert(bin_find(m, m->dv) == 0);
}
 
if (m->top != 0) { /* check top chunk */
do_check_top_chunk(m, m->top);
assert(m->topsize == chunksize(m->top));
assert(m->topsize > 0);
assert(bin_find(m, m->top) == 0);
}
 
total = traverse_and_check(m);
assert(total <= m->footprint);
assert(m->footprint <= m->max_footprint);
}
#endif /* DEBUG */
 
/* ----------------------------- statistics ------------------------------ */
 
#if !NO_MALLINFO
static struct mallinfo internal_mallinfo(mstate m) {
struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
if (!PREACTION(m)) {
check_malloc_state(m);
if (is_initialized(m)) {
size_t nfree = SIZE_T_ONE; /* top always free */
size_t mfree = m->topsize + TOP_FOOT_SIZE;
size_t sum = mfree;
msegmentptr s = &m->seg;
while (s != 0) {
mchunkptr q = align_as_chunk(s->base);
while (segment_holds(s, q) &&
q != m->top && q->head != FENCEPOST_HEAD) {
size_t sz = chunksize(q);
sum += sz;
if (!cinuse(q)) {
mfree += sz;
++nfree;
}
q = next_chunk(q);
}
s = s->next;
}
 
nm.arena = sum;
nm.ordblks = nfree;
nm.hblkhd = m->footprint - sum;
nm.usmblks = m->max_footprint;
nm.uordblks = m->footprint - mfree;
nm.fordblks = mfree;
nm.keepcost = m->topsize;
}
 
POSTACTION(m);
}
return nm;
}
#endif /* !NO_MALLINFO */
 
static void internal_malloc_stats(mstate m) {
if (!PREACTION(m)) {
size_t maxfp = 0;
size_t fp = 0;
size_t used = 0;
check_malloc_state(m);
if (is_initialized(m)) {
msegmentptr s = &m->seg;
maxfp = m->max_footprint;
fp = m->footprint;
used = fp - (m->topsize + TOP_FOOT_SIZE);
 
while (s != 0) {
mchunkptr q = align_as_chunk(s->base);
while (segment_holds(s, q) &&
q != m->top && q->head != FENCEPOST_HEAD) {
if (!cinuse(q))
used -= chunksize(q);
q = next_chunk(q);
}
s = s->next;
}
}
 
fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
 
POSTACTION(m);
}
}
 
/* ----------------------- Operations on smallbins ----------------------- */
 
/*
Various forms of linking and unlinking are defined as macros. Even
the ones for trees, which are very long but have very short typical
paths. This is ugly but reduces reliance on inlining support of
compilers.
*/
 
/* Link a free chunk into a smallbin */
#define insert_small_chunk(M, P, S) {\
bindex_t I = small_index(S);\
mchunkptr B = smallbin_at(M, I);\
mchunkptr F = B;\
assert(S >= MIN_CHUNK_SIZE);\
if (!smallmap_is_marked(M, I))\
mark_smallmap(M, I);\
else if (RTCHECK(ok_address(M, B->fd)))\
F = B->fd;\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
B->fd = P;\
F->bk = P;\
P->fd = F;\
P->bk = B;\
}
 
/* Unlink a chunk from a smallbin */
#define unlink_small_chunk(M, P, S) {\
mchunkptr F = P->fd;\
mchunkptr B = P->bk;\
bindex_t I = small_index(S);\
assert(P != B);\
assert(P != F);\
assert(chunksize(P) == small_index2size(I));\
if (F == B)\
clear_smallmap(M, I);\
else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
(B == smallbin_at(M,I) || ok_address(M, B)))) {\
F->bk = B;\
B->fd = F;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}
 
/* Unlink the first chunk from a smallbin */
#define unlink_first_small_chunk(M, B, P, I) {\
mchunkptr F = P->fd;\
assert(P != B);\
assert(P != F);\
assert(chunksize(P) == small_index2size(I));\
if (B == F)\
clear_smallmap(M, I);\
else if (RTCHECK(ok_address(M, F))) {\
B->fd = F;\
F->bk = B;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}
 
/* Replace dv node, binning the old one */
/* Used only when dvsize known to be small */
#define replace_dv(M, P, S) {\
size_t DVS = M->dvsize;\
if (DVS != 0) {\
mchunkptr DV = M->dv;\
assert(is_small(DVS));\
insert_small_chunk(M, DV, DVS);\
}\
M->dvsize = S;\
M->dv = P;\
}
 
/* ------------------------- Operations on trees ------------------------- */
 
/* Insert chunk into tree */
#define insert_large_chunk(M, X, S) {\
tbinptr* H;\
bindex_t I;\
compute_tree_index(S, I);\
H = treebin_at(M, I);\
X->index = I;\
X->child[0] = X->child[1] = 0;\
if (!treemap_is_marked(M, I)) {\
mark_treemap(M, I);\
*H = X;\
X->parent = (tchunkptr)H;\
X->fd = X->bk = X;\
}\
else {\
tchunkptr T = *H;\
size_t K = S << leftshift_for_tree_index(I);\
for (;;) {\
if (chunksize(T) != S) {\
tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
K <<= 1;\
if (*C != 0)\
T = *C;\
else if (RTCHECK(ok_address(M, C))) {\
*C = X;\
X->parent = T;\
X->fd = X->bk = X;\
break;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
break;\
}\
}\
else {\
tchunkptr F = T->fd;\
if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
T->fd = F->bk = X;\
X->fd = F;\
X->bk = T;\
X->parent = 0;\
break;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
break;\
}\
}\
}\
}\
}
 
/*
Unlink steps:
 
1. If x is a chained node, unlink it from its same-sized fd/bk links
and choose its bk node as its replacement.
2. If x was the last node of its size, but not a leaf node, it must
be replaced with a leaf node (not merely one with an open left or
right), to make sure that lefts and rights of descendents
correspond properly to bit masks. We use the rightmost descendent
of x. We could use any other leaf, but this is easy to locate and
tends to counteract removal of leftmosts elsewhere, and so keeps
paths shorter than minimally guaranteed. This doesn't loop much
because on average a node in a tree is near the bottom.
3. If x is the base of a chain (i.e., has parent links) relink
x's parent and children to x's replacement (or null if none).
*/
 
#define unlink_large_chunk(M, X) {\
tchunkptr XP = X->parent;\
tchunkptr R;\
if (X->bk != X) {\
tchunkptr F = X->fd;\
R = X->bk;\
if (RTCHECK(ok_address(M, F))) {\
F->bk = R;\
R->fd = F;\
}\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
else {\
tchunkptr* RP;\
if (((R = *(RP = &(X->child[1]))) != 0) ||\
((R = *(RP = &(X->child[0]))) != 0)) {\
tchunkptr* CP;\
while ((*(CP = &(R->child[1])) != 0) ||\
(*(CP = &(R->child[0])) != 0)) {\
R = *(RP = CP);\
}\
if (RTCHECK(ok_address(M, RP)))\
*RP = 0;\
else {\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
}\
if (XP != 0) {\
tbinptr* H = treebin_at(M, X->index);\
if (X == *H) {\
if ((*H = R) == 0) \
clear_treemap(M, X->index);\
}\
else if (RTCHECK(ok_address(M, XP))) {\
if (XP->child[0] == X) \
XP->child[0] = R;\
else \
XP->child[1] = R;\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
if (R != 0) {\
if (RTCHECK(ok_address(M, R))) {\
tchunkptr C0, C1;\
R->parent = XP;\
if ((C0 = X->child[0]) != 0) {\
if (RTCHECK(ok_address(M, C0))) {\
R->child[0] = C0;\
C0->parent = R;\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
}\
if ((C1 = X->child[1]) != 0) {\
if (RTCHECK(ok_address(M, C1))) {\
R->child[1] = C1;\
C1->parent = R;\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
else\
CORRUPTION_ERROR_ACTION(M);\
}\
}\
}
 
/* Relays to large vs small bin operations */
 
#define insert_chunk(M, P, S)\
if (is_small(S)) insert_small_chunk(M, P, S)\
else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
 
#define unlink_chunk(M, P, S)\
if (is_small(S)) unlink_small_chunk(M, P, S)\
else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
 
 
/* Relays to internal calls to malloc/free from realloc, memalign etc */
 
#if ONLY_MSPACES
#define internal_malloc(m, b) mspace_malloc(m, b)
#define internal_free(m, mem) mspace_free(m,mem);
#else /* ONLY_MSPACES */
#if MSPACES
#define internal_malloc(m, b)\
(m == gm)? dlmalloc(b) : mspace_malloc(m, b)
#define internal_free(m, mem)\
if (m == gm) dlfree(mem); else mspace_free(m,mem);
#else /* MSPACES */
#define internal_malloc(m, b) dlmalloc(b)
#define internal_free(m, mem) dlfree(mem)
#endif /* MSPACES */
#endif /* ONLY_MSPACES */
 
/* ----------------------- Direct-mmapping chunks ----------------------- */
 
/*
Directly mmapped chunks are set up with an offset to the start of
the mmapped region stored in the prev_foot field of the chunk. This
allows reconstruction of the required argument to MUNMAP when freed,
and also allows adjustment of the returned chunk to meet alignment
requirements (especially in memalign). There is also enough space
allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
the PINUSE bit so frees can be checked.
*/
 
/* Malloc using mmap */
static void* mmap_alloc(mstate m, size_t nb) {
size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
if (mmsize > nb) { /* Check for wrap around 0 */
char* mm = (char*)(DIRECT_MMAP(mmsize));
if (mm != CMFAIL) {
size_t offset = align_offset(chunk2mem(mm));
size_t psize = mmsize - offset - MMAP_FOOT_PAD;
mchunkptr p = (mchunkptr)(mm + offset);
p->prev_foot = offset | IS_MMAPPED_BIT;
(p)->head = (psize|CINUSE_BIT);
mark_inuse_foot(m, p, psize);
chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
 
if (mm < m->least_addr)
m->least_addr = mm;
if ((m->footprint += mmsize) > m->max_footprint)
m->max_footprint = m->footprint;
assert(is_aligned(chunk2mem(p)));
check_mmapped_chunk(m, p);
return chunk2mem(p);
}
}
return 0;
}
 
/* Realloc using mmap */
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
size_t oldsize = chunksize(oldp);
if (is_small(nb)) /* Can't shrink mmap regions below small size */
return 0;
/* Keep old chunk if big enough but not too big */
if (oldsize >= nb + SIZE_T_SIZE &&
(oldsize - nb) <= (mparams.granularity << 1))
return oldp;
else {
size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
CHUNK_ALIGN_MASK);
char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
oldmmsize, newmmsize, 1);
if (cp != CMFAIL) {
mchunkptr newp = (mchunkptr)(cp + offset);
size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
newp->head = (psize|CINUSE_BIT);
mark_inuse_foot(m, newp, psize);
chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
 
if (cp < m->least_addr)
m->least_addr = cp;
if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
m->max_footprint = m->footprint;
check_mmapped_chunk(m, newp);
return newp;
}
}
return 0;
}
 
/* -------------------------- mspace management -------------------------- */
 
/* Initialize top chunk and its size */
static void init_top(mstate m, mchunkptr p, size_t psize) {
/* Ensure alignment */
size_t offset = align_offset(chunk2mem(p));
p = (mchunkptr)((char*)p + offset);
psize -= offset;
 
m->top = p;
m->topsize = psize;
p->head = psize | PINUSE_BIT;
/* set size of fake trailing chunk holding overhead space only once */
chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
m->trim_check = mparams.trim_threshold; /* reset on each update */
}
 
/* Initialize bins for a new mstate that is otherwise zeroed out */
static void init_bins(mstate m) {
/* Establish circular links for smallbins */
bindex_t i;
for (i = 0; i < NSMALLBINS; ++i) {
sbinptr bin = smallbin_at(m,i);
bin->fd = bin->bk = bin;
}
}
 
#if PROCEED_ON_ERROR
 
/* default corruption action */
static void reset_on_error(mstate m) {
int i;
++malloc_corruption_error_count;
/* Reinitialize fields to forget about all memory */
m->smallbins = m->treebins = 0;
m->dvsize = m->topsize = 0;
m->seg.base = 0;
m->seg.size = 0;
m->seg.next = 0;
m->top = m->dv = 0;
for (i = 0; i < NTREEBINS; ++i)
*treebin_at(m, i) = 0;
init_bins(m);
}
#endif /* PROCEED_ON_ERROR */
 
/* Allocate chunk and prepend remainder with chunk in successor base. */
static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
size_t nb) {
mchunkptr p = align_as_chunk(newbase);
mchunkptr oldfirst = align_as_chunk(oldbase);
size_t psize = (char*)oldfirst - (char*)p;
mchunkptr q = chunk_plus_offset(p, nb);
size_t qsize = psize - nb;
set_size_and_pinuse_of_inuse_chunk(m, p, nb);
 
assert((char*)oldfirst > (char*)q);
assert(pinuse(oldfirst));
assert(qsize >= MIN_CHUNK_SIZE);
 
/* consolidate remainder with first chunk of old base */
if (oldfirst == m->top) {
size_t tsize = m->topsize += qsize;
m->top = q;
q->head = tsize | PINUSE_BIT;
check_top_chunk(m, q);
}
else if (oldfirst == m->dv) {
size_t dsize = m->dvsize += qsize;
m->dv = q;
set_size_and_pinuse_of_free_chunk(q, dsize);
}
else {
if (!cinuse(oldfirst)) {
size_t nsize = chunksize(oldfirst);
unlink_chunk(m, oldfirst, nsize);
oldfirst = chunk_plus_offset(oldfirst, nsize);
qsize += nsize;
}
set_free_with_pinuse(q, qsize, oldfirst);
insert_chunk(m, q, qsize);
check_free_chunk(m, q);
}
 
check_malloced_chunk(m, chunk2mem(p), nb);
return chunk2mem(p);
}
 
 
/* Add a segment to hold a new noncontiguous region */
static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
/* Determine locations and sizes of segment, fenceposts, old top */
char* old_top = (char*)m->top;
msegmentptr oldsp = segment_holding(m, old_top);
char* old_end = oldsp->base + oldsp->size;
size_t ssize = pad_request(sizeof(struct malloc_segment));
char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
size_t offset = align_offset(chunk2mem(rawsp));
char* asp = rawsp + offset;
char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
mchunkptr sp = (mchunkptr)csp;
msegmentptr ss = (msegmentptr)(chunk2mem(sp));
mchunkptr tnext = chunk_plus_offset(sp, ssize);
mchunkptr p = tnext;
int nfences = 0;
 
/* reset top to new space */
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
 
/* Set up segment record */
assert(is_aligned(ss));
set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
*ss = m->seg; /* Push current record */
m->seg.base = tbase;
m->seg.size = tsize;
m->seg.sflags = mmapped;
m->seg.next = ss;
 
/* Insert trailing fenceposts */
for (;;) {
mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
p->head = FENCEPOST_HEAD;
++nfences;
if ((char*)(&(nextp->head)) < old_end)
p = nextp;
else
break;
}
assert(nfences >= 2);
 
/* Insert the rest of old top into a bin as an ordinary free chunk */
if (csp != old_top) {
mchunkptr q = (mchunkptr)old_top;
size_t psize = csp - old_top;
mchunkptr tn = chunk_plus_offset(q, psize);
set_free_with_pinuse(q, psize, tn);
insert_chunk(m, q, psize);
}
 
check_top_chunk(m, m->top);
}
 
/* -------------------------- System allocation -------------------------- */
 
/* Get memory from system using MORECORE or MMAP */
static void* sys_alloc(mstate m, size_t nb) {
char* tbase = CMFAIL;
size_t tsize = 0;
flag_t mmap_flag = 0;
 
init_mparams();
 
/* Directly map large chunks */
if (use_mmap(m) && nb >= mparams.mmap_threshold) {
void* mem = mmap_alloc(m, nb);
if (mem != 0)
return mem;
}
 
/*
Try getting memory in any of three ways (in most-preferred to
least-preferred order):
1. A call to MORECORE that can normally contiguously extend memory.
(disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
or main space is mmapped or a previous contiguous call failed)
2. A call to MMAP new space (disabled if not HAVE_MMAP).
Note that under the default settings, if MORECORE is unable to
fulfill a request, and HAVE_MMAP is true, then mmap is
used as a noncontiguous system allocator. This is a useful backup
strategy for systems with holes in address spaces -- in this case
sbrk cannot contiguously expand the heap, but mmap may be able to
find space.
3. A call to MORECORE that cannot usually contiguously extend memory.
(disabled if not HAVE_MORECORE)
*/
 
if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
char* br = CMFAIL;
msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
size_t asize = 0;
ACQUIRE_MORECORE_LOCK();
 
if (ss == 0) { /* First time through or recovery */
char* base = (char*)CALL_MORECORE(0);
if (base != CMFAIL) {
asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
/* Adjust to end on a page boundary */
if (!is_page_aligned(base))
asize += (page_align((size_t)base) - (size_t)base);
/* Can't call MORECORE if size is negative when treated as signed */
if (asize < HALF_MAX_SIZE_T &&
(br = (char*)(CALL_MORECORE(asize))) == base) {
tbase = base;
tsize = asize;
}
}
}
else {
/* Subtract out existing available top space from MORECORE request. */
asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
/* Use mem here only if it did continuously extend old space */
if (asize < HALF_MAX_SIZE_T &&
(br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
tbase = br;
tsize = asize;
}
}
 
if (tbase == CMFAIL) { /* Cope with partial failure */
if (br != CMFAIL) { /* Try to use/extend the space we did get */
if (asize < HALF_MAX_SIZE_T &&
asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
if (esize < HALF_MAX_SIZE_T) {
char* end = (char*)CALL_MORECORE(esize);
if (end != CMFAIL)
asize += esize;
else { /* Can't use; try to release */
CALL_MORECORE(-asize);
br = CMFAIL;
}
}
}
}
if (br != CMFAIL) { /* Use the space we did get */
tbase = br;
tsize = asize;
}
else
disable_contiguous(m); /* Don't try contiguous path in the future */
}
 
RELEASE_MORECORE_LOCK();
}
 
if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */
size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
size_t rsize = granularity_align(req);
if (rsize > nb) { /* Fail if wraps around zero */
char* mp = (char*)(CALL_MMAP(rsize));
if (mp != CMFAIL) {
tbase = mp;
tsize = rsize;
mmap_flag = IS_MMAPPED_BIT;
}
}
}
 
if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
if (asize < HALF_MAX_SIZE_T) {
char* br = CMFAIL;
char* end = CMFAIL;
ACQUIRE_MORECORE_LOCK();
br = (char*)(CALL_MORECORE(asize));
end = (char*)(CALL_MORECORE(0));
RELEASE_MORECORE_LOCK();
if (br != CMFAIL && end != CMFAIL && br < end) {
size_t ssize = end - br;
if (ssize > nb + TOP_FOOT_SIZE) {
tbase = br;
tsize = ssize;
}
}
}
}
 
if (tbase != CMFAIL) {
 
if ((m->footprint += tsize) > m->max_footprint)
m->max_footprint = m->footprint;
 
if (!is_initialized(m)) { /* first-time initialization */
m->seg.base = m->least_addr = tbase;
m->seg.size = tsize;
m->seg.sflags = mmap_flag;
m->magic = mparams.magic;
init_bins(m);
if (is_global(m))
init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
else {
/* Offset top by embedded malloc_state */
mchunkptr mn = next_chunk(mem2chunk(m));
init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
}
}
 
else {
/* Try to merge with an existing segment */
msegmentptr sp = &m->seg;
while (sp != 0 && tbase != sp->base + sp->size)
sp = sp->next;
if (sp != 0 &&
!is_extern_segment(sp) &&
(sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
segment_holds(sp, m->top)) { /* append */
sp->size += tsize;
init_top(m, m->top, m->topsize + tsize);
}
else {
if (tbase < m->least_addr)
m->least_addr = tbase;
sp = &m->seg;
while (sp != 0 && sp->base != tbase + tsize)
sp = sp->next;
if (sp != 0 &&
!is_extern_segment(sp) &&
(sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
char* oldbase = sp->base;
sp->base = tbase;
sp->size += tsize;
return prepend_alloc(m, tbase, oldbase, nb);
}
else
add_segment(m, tbase, tsize, mmap_flag);
}
}
 
if (nb < m->topsize) { /* Allocate from new or extended top space */
size_t rsize = m->topsize -= nb;
mchunkptr p = m->top;
mchunkptr r = m->top = chunk_plus_offset(p, nb);
r->head = rsize | PINUSE_BIT;
set_size_and_pinuse_of_inuse_chunk(m, p, nb);
check_top_chunk(m, m->top);
check_malloced_chunk(m, chunk2mem(p), nb);
return chunk2mem(p);
}
}
 
MALLOC_FAILURE_ACTION;
return 0;
}
 
/* ----------------------- system deallocation -------------------------- */
 
/* Unmap and unlink any mmapped segments that don't contain used chunks */
static size_t release_unused_segments(mstate m) {
size_t released = 0;
msegmentptr pred = &m->seg;
msegmentptr sp = pred->next;
while (sp != 0) {
char* base = sp->base;
size_t size = sp->size;
msegmentptr next = sp->next;
if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
mchunkptr p = align_as_chunk(base);
size_t psize = chunksize(p);
/* Can unmap if first chunk holds entire segment and not pinned */
if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
tchunkptr tp = (tchunkptr)p;
assert(segment_holds(sp, (char*)sp));
if (p == m->dv) {
m->dv = 0;
m->dvsize = 0;
}
else {
unlink_large_chunk(m, tp);
}
if (CALL_MUNMAP(base, size) == 0) {
released += size;
m->footprint -= size;
/* unlink obsoleted record */
sp = pred;
sp->next = next;
}
else { /* back out if cannot unmap */
insert_large_chunk(m, tp, psize);
}
}
}
pred = sp;
sp = next;
}
return released;
}
 
static int sys_trim(mstate m, size_t pad) {
size_t released = 0;
if (pad < MAX_REQUEST && is_initialized(m)) {
pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
 
if (m->topsize > pad) {
/* Shrink top space in granularity-size units, keeping at least one */
size_t unit = mparams.granularity;
size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
SIZE_T_ONE) * unit;
msegmentptr sp = segment_holding(m, (char*)m->top);
 
if (!is_extern_segment(sp)) {
if (is_mmapped_segment(sp)) {
if (HAVE_MMAP &&
sp->size >= extra &&
!has_segment_link(m, sp)) { /* can't shrink if pinned */
/* Prefer mremap, fall back to munmap */
if ((CALL_MREMAP(sp->base, sp->size, sp->size - extra, 0) != MFAIL) ||
(CALL_MUNMAP(sp->base + sp->size - extra, extra) == 0)) {
released = extra;
}
}
}
else if (HAVE_MORECORE) {
if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
ACQUIRE_MORECORE_LOCK();
{
/* Make sure end of memory is where we last set it. */
char* old_br = (char*)(CALL_MORECORE(0));
if (old_br == sp->base + sp->size) {
char* rel_br = (char*)(CALL_MORECORE(-extra));
char* new_br = (char*)(CALL_MORECORE(0));
if (rel_br != CMFAIL && new_br < old_br)
released = old_br - new_br;
}
}
RELEASE_MORECORE_LOCK();
}
}
 
if (released != 0) {
sp->size -= released;
m->footprint -= released;
init_top(m, m->top, m->topsize - released);
check_top_chunk(m, m->top);
}
}
 
/* Unmap any unused mmapped segments */
if (HAVE_MMAP)
released += release_unused_segments(m);
 
/* On failure, disable autotrim to avoid repeated failed future calls */
if (released == 0)
m->trim_check = MAX_SIZE_T;
}
 
return (released != 0)? 1 : 0;
}
 
/* ---------------------------- malloc support --------------------------- */
 
/* allocate a large request from the best fitting chunk in a treebin */
static void* tmalloc_large(mstate m, size_t nb) {
tchunkptr v = 0;
size_t rsize = -nb; /* Unsigned negation */
tchunkptr t;
bindex_t idx;
compute_tree_index(nb, idx);
 
if ((t = *treebin_at(m, idx)) != 0) {
/* Traverse tree for this bin looking for node with size == nb */
size_t sizebits = nb << leftshift_for_tree_index(idx);
tchunkptr rst = 0; /* The deepest untaken right subtree */
for (;;) {
tchunkptr rt;
size_t trem = chunksize(t) - nb;
if (trem < rsize) {
v = t;
if ((rsize = trem) == 0)
break;
}
rt = t->child[1];
t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
if (rt != 0 && rt != t)
rst = rt;
if (t == 0) {
t = rst; /* set t to least subtree holding sizes > nb */
break;
}
sizebits <<= 1;
}
}
 
if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
if (leftbits != 0) {
bindex_t i;
binmap_t leastbit = least_bit(leftbits);
compute_bit2idx(leastbit, i);
t = *treebin_at(m, i);
}
}
 
while (t != 0) { /* find smallest of tree or subtree */
size_t trem = chunksize(t) - nb;
if (trem < rsize) {
rsize = trem;
v = t;
}
t = leftmost_child(t);
}
 
/* If dv is a better fit, return 0 so malloc will use it */
if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
if (RTCHECK(ok_address(m, v))) { /* split */
mchunkptr r = chunk_plus_offset(v, nb);
assert(chunksize(v) == rsize + nb);
if (RTCHECK(ok_next(v, r))) {
unlink_large_chunk(m, v);
if (rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(m, v, (rsize + nb));
else {
set_size_and_pinuse_of_inuse_chunk(m, v, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
insert_chunk(m, r, rsize);
}
return chunk2mem(v);
}
}
CORRUPTION_ERROR_ACTION(m);
}
return 0;
}
 
/* allocate a small request from the best fitting chunk in a treebin */
static void* tmalloc_small(mstate m, size_t nb) {
tchunkptr t, v;
size_t rsize;
bindex_t i;
binmap_t leastbit = least_bit(m->treemap);
compute_bit2idx(leastbit, i);
 
v = t = *treebin_at(m, i);
rsize = chunksize(t) - nb;
 
while ((t = leftmost_child(t)) != 0) {
size_t trem = chunksize(t) - nb;
if (trem < rsize) {
rsize = trem;
v = t;
}
}
 
if (RTCHECK(ok_address(m, v))) {
mchunkptr r = chunk_plus_offset(v, nb);
assert(chunksize(v) == rsize + nb);
if (RTCHECK(ok_next(v, r))) {
unlink_large_chunk(m, v);
if (rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(m, v, (rsize + nb));
else {
set_size_and_pinuse_of_inuse_chunk(m, v, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
replace_dv(m, r, rsize);
}
return chunk2mem(v);
}
}
 
CORRUPTION_ERROR_ACTION(m);
return 0;
}
 
/* --------------------------- realloc support --------------------------- */
 
static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
if (bytes >= MAX_REQUEST) {
MALLOC_FAILURE_ACTION;
return 0;
}
if (!PREACTION(m)) {
mchunkptr oldp = mem2chunk(oldmem);
size_t oldsize = chunksize(oldp);
mchunkptr next = chunk_plus_offset(oldp, oldsize);
mchunkptr newp = 0;
void* extra = 0;
 
/* Try to either shrink or extend into top. Else malloc-copy-free */
 
if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
ok_next(oldp, next) && ok_pinuse(next))) {
size_t nb = request2size(bytes);
if (is_mmapped(oldp))
newp = mmap_resize(m, oldp, nb);
else if (oldsize >= nb) { /* already big enough */
size_t rsize = oldsize - nb;
newp = oldp;
if (rsize >= MIN_CHUNK_SIZE) {
mchunkptr remainder = chunk_plus_offset(newp, nb);
set_inuse(m, newp, nb);
set_inuse(m, remainder, rsize);
extra = chunk2mem(remainder);
}
}
else if (next == m->top && oldsize + m->topsize > nb) {
/* Expand into top */
size_t newsize = oldsize + m->topsize;
size_t newtopsize = newsize - nb;
mchunkptr newtop = chunk_plus_offset(oldp, nb);
set_inuse(m, oldp, nb);
newtop->head = newtopsize |PINUSE_BIT;
m->top = newtop;
m->topsize = newtopsize;
newp = oldp;
}
}
else {
USAGE_ERROR_ACTION(m, oldmem);
POSTACTION(m);
return 0;
}
 
POSTACTION(m);
 
if (newp != 0) {
if (extra != 0) {
internal_free(m, extra);
}
check_inuse_chunk(m, newp);
return chunk2mem(newp);
}
else {
void* newmem = internal_malloc(m, bytes);
if (newmem != 0) {
size_t oc = oldsize - overhead_for(oldp);
memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
internal_free(m, oldmem);
}
return newmem;
}
}
return 0;
}
 
/* --------------------------- memalign support -------------------------- */
 
static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */
return internal_malloc(m, bytes);
if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
alignment = MIN_CHUNK_SIZE;
if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
size_t a = MALLOC_ALIGNMENT << 1;
while (a < alignment) a <<= 1;
alignment = a;
}
if (bytes >= MAX_REQUEST - alignment) {
if (m != 0) { /* Test isn't needed but avoids compiler warning */
MALLOC_FAILURE_ACTION;
}
}
else {
size_t nb = request2size(bytes);
size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
char* mem = (char*)internal_malloc(m, req);
if (mem != 0) {
void* leader = 0;
void* trailer = 0;
mchunkptr p = mem2chunk(mem);
 
if (PREACTION(m)) return 0;
if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
/*
Find an aligned spot inside chunk. Since we need to give
back leading space in a chunk of at least MIN_CHUNK_SIZE, if
the first calculation places us at a spot with less than
MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
We've allocated enough total room so that this is always
possible.
*/
char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
alignment -
SIZE_T_ONE)) &
-alignment));
char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
br : br+alignment;
mchunkptr newp = (mchunkptr)pos;
size_t leadsize = pos - (char*)(p);
size_t newsize = chunksize(p) - leadsize;
 
if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
newp->prev_foot = p->prev_foot + leadsize;
newp->head = (newsize|CINUSE_BIT);
}
else { /* Otherwise, give back leader, use the rest */
set_inuse(m, newp, newsize);
set_inuse(m, p, leadsize);
leader = chunk2mem(p);
}
p = newp;
}
 
/* Give back spare room at the end */
if (!is_mmapped(p)) {
size_t size = chunksize(p);
if (size > nb + MIN_CHUNK_SIZE) {
size_t remainder_size = size - nb;
mchunkptr remainder = chunk_plus_offset(p, nb);
set_inuse(m, p, nb);
set_inuse(m, remainder, remainder_size);
trailer = chunk2mem(remainder);
}
}
 
assert (chunksize(p) >= nb);
assert((((size_t)(chunk2mem(p))) % alignment) == 0);
check_inuse_chunk(m, p);
POSTACTION(m);
if (leader != 0) {
internal_free(m, leader);
}
if (trailer != 0) {
internal_free(m, trailer);
}
return chunk2mem(p);
}
}
return 0;
}
 
/* ------------------------ comalloc/coalloc support --------------------- */
 
static void** ialloc(mstate m,
size_t n_elements,
size_t* sizes,
int opts,
void* chunks[]) {
/*
This provides common support for independent_X routines, handling
all of the combinations that can result.
 
The opts arg has:
bit 0 set if all elements are same size (using sizes[0])
bit 1 set if elements should be zeroed
*/
 
size_t element_size; /* chunksize of each element, if all same */
size_t contents_size; /* total size of elements */
size_t array_size; /* request size of pointer array */
void* mem; /* malloced aggregate space */
mchunkptr p; /* corresponding chunk */
size_t remainder_size; /* remaining bytes while splitting */
void** marray; /* either "chunks" or malloced ptr array */
mchunkptr array_chunk; /* chunk for malloced ptr array */
flag_t was_enabled; /* to disable mmap */
size_t size;
size_t i;
 
/* compute array length, if needed */
if (chunks != 0) {
if (n_elements == 0)
return chunks; /* nothing to do */
marray = chunks;
array_size = 0;
}
else {
/* if empty req, must still return chunk representing empty array */
if (n_elements == 0)
return (void**)internal_malloc(m, 0);
marray = 0;
array_size = request2size(n_elements * (sizeof(void*)));
}
 
/* compute total element size */
if (opts & 0x1) { /* all-same-size */
element_size = request2size(*sizes);
contents_size = n_elements * element_size;
}
else { /* add up all the sizes */
element_size = 0;
contents_size = 0;
for (i = 0; i != n_elements; ++i)
contents_size += request2size(sizes[i]);
}
 
size = contents_size + array_size;
 
/*
Allocate the aggregate chunk. First disable direct-mmapping so
malloc won't use it, since we would not be able to later
free/realloc space internal to a segregated mmap region.
*/
was_enabled = use_mmap(m);
disable_mmap(m);
mem = internal_malloc(m, size - CHUNK_OVERHEAD);
if (was_enabled)
enable_mmap(m);
if (mem == 0)
return 0;
 
if (PREACTION(m)) return 0;
p = mem2chunk(mem);
remainder_size = chunksize(p);
 
assert(!is_mmapped(p));
 
if (opts & 0x2) { /* optionally clear the elements */
memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
}
 
/* If not provided, allocate the pointer array as final part of chunk */
if (marray == 0) {
size_t array_chunk_size;
array_chunk = chunk_plus_offset(p, contents_size);
array_chunk_size = remainder_size - contents_size;
marray = (void**) (chunk2mem(array_chunk));
set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
remainder_size = contents_size;
}
 
/* split out elements */
for (i = 0; ; ++i) {
marray[i] = chunk2mem(p);
if (i != n_elements-1) {
if (element_size != 0)
size = element_size;
else
size = request2size(sizes[i]);
remainder_size -= size;
set_size_and_pinuse_of_inuse_chunk(m, p, size);
p = chunk_plus_offset(p, size);
}
else { /* the final element absorbs any overallocation slop */
set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
break;
}
}
 
#if DEBUG
if (marray != chunks) {
/* final element must have exactly exhausted chunk */
if (element_size != 0) {
assert(remainder_size == element_size);
}
else {
assert(remainder_size == request2size(sizes[i]));
}
check_inuse_chunk(m, mem2chunk(marray));
}
for (i = 0; i != n_elements; ++i)
check_inuse_chunk(m, mem2chunk(marray[i]));
 
#endif /* DEBUG */
 
POSTACTION(m);
return marray;
}
 
 
/* -------------------------- public routines ---------------------------- */
 
#if !ONLY_MSPACES
 
void* dlmalloc(size_t bytes) {
/*
Basic algorithm:
If a small request (< 256 bytes minus per-chunk overhead):
1. If one exists, use a remainderless chunk in associated smallbin.
(Remainderless means that there are too few excess bytes to
represent as a chunk.)
2. If it is big enough, use the dv chunk, which is normally the
chunk adjacent to the one used for the most recent small request.
3. If one exists, split the smallest available chunk in a bin,
saving remainder in dv.
4. If it is big enough, use the top chunk.
5. If available, get memory from system and use it
Otherwise, for a large request:
1. Find the smallest available binned chunk that fits, and use it
if it is better fitting than dv chunk, splitting if necessary.
2. If better fitting than any binned chunk, use the dv chunk.
3. If it is big enough, use the top chunk.
4. If request size >= mmap threshold, try to directly mmap this chunk.
5. If available, get memory from system and use it
 
The ugly goto's here ensure that postaction occurs along all paths.
*/
 
if (!PREACTION(gm)) {
void* mem;
size_t nb;
if (bytes <= MAX_SMALL_REQUEST) {
bindex_t idx;
binmap_t smallbits;
nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
idx = small_index(nb);
smallbits = gm->smallmap >> idx;
 
if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
mchunkptr b, p;
idx += ~smallbits & 1; /* Uses next bin if idx empty */
b = smallbin_at(gm, idx);
p = b->fd;
assert(chunksize(p) == small_index2size(idx));
unlink_first_small_chunk(gm, b, p, idx);
set_inuse_and_pinuse(gm, p, small_index2size(idx));
mem = chunk2mem(p);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
 
else if (nb > gm->dvsize) {
if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
mchunkptr b, p, r;
size_t rsize;
bindex_t i;
binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
binmap_t leastbit = least_bit(leftbits);
compute_bit2idx(leastbit, i);
b = smallbin_at(gm, i);
p = b->fd;
assert(chunksize(p) == small_index2size(i));
unlink_first_small_chunk(gm, b, p, i);
rsize = small_index2size(i) - nb;
/* Fit here cannot be remainderless if 4byte sizes */
if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(gm, p, small_index2size(i));
else {
set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
r = chunk_plus_offset(p, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
replace_dv(gm, r, rsize);
}
mem = chunk2mem(p);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
 
else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
}
}
else if (bytes >= MAX_REQUEST)
nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
else {
nb = pad_request(bytes);
if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
}
 
if (nb <= gm->dvsize) {
size_t rsize = gm->dvsize - nb;
mchunkptr p = gm->dv;
if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
gm->dvsize = rsize;
set_size_and_pinuse_of_free_chunk(r, rsize);
set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
}
else { /* exhaust dv */
size_t dvs = gm->dvsize;
gm->dvsize = 0;
gm->dv = 0;
set_inuse_and_pinuse(gm, p, dvs);
}
mem = chunk2mem(p);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
 
else if (nb < gm->topsize) { /* Split top */
size_t rsize = gm->topsize -= nb;
mchunkptr p = gm->top;
mchunkptr r = gm->top = chunk_plus_offset(p, nb);
r->head = rsize | PINUSE_BIT;
set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
mem = chunk2mem(p);
check_top_chunk(gm, gm->top);
check_malloced_chunk(gm, mem, nb);
goto postaction;
}
 
mem = sys_alloc(gm, nb);
 
postaction:
POSTACTION(gm);
return mem;
}
 
return 0;
}
 
void dlfree(void* mem) {
/*
Consolidate freed chunks with preceeding or succeeding bordering
free chunks, if they exist, and then place in a bin. Intermixed
with special cases for top, dv, mmapped chunks, and usage errors.
*/
 
if (mem != 0) {
mchunkptr p = mem2chunk(mem);
#if FOOTERS
mstate fm = get_mstate_for(p);
if (!ok_magic(fm)) {
USAGE_ERROR_ACTION(fm, p);
return;
}
#else /* FOOTERS */
#define fm gm
#endif /* FOOTERS */
if (!PREACTION(fm)) {
check_inuse_chunk(fm, p);
if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
size_t psize = chunksize(p);
mchunkptr next = chunk_plus_offset(p, psize);
if (!pinuse(p)) {
size_t prevsize = p->prev_foot;
if ((prevsize & IS_MMAPPED_BIT) != 0) {
prevsize &= ~IS_MMAPPED_BIT;
psize += prevsize + MMAP_FOOT_PAD;
if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
fm->footprint -= psize;
goto postaction;
}
else {
mchunkptr prev = chunk_minus_offset(p, prevsize);
psize += prevsize;
p = prev;
if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
if (p != fm->dv) {
unlink_chunk(fm, p, prevsize);
}
else if ((next->head & INUSE_BITS) == INUSE_BITS) {
fm->dvsize = psize;
set_free_with_pinuse(p, psize, next);
goto postaction;
}
}
else
goto erroraction;
}
}
 
if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
if (!cinuse(next)) { /* consolidate forward */
if (next == fm->top) {
size_t tsize = fm->topsize += psize;
fm->top = p;
p->head = tsize | PINUSE_BIT;
if (p == fm->dv) {
fm->dv = 0;
fm->dvsize = 0;
}
if (should_trim(fm, tsize))
sys_trim(fm, 0);
goto postaction;
}
else if (next == fm->dv) {
size_t dsize = fm->dvsize += psize;
fm->dv = p;
set_size_and_pinuse_of_free_chunk(p, dsize);
goto postaction;
}
else {
size_t nsize = chunksize(next);
psize += nsize;
unlink_chunk(fm, next, nsize);
set_size_and_pinuse_of_free_chunk(p, psize);
if (p == fm->dv) {
fm->dvsize = psize;
goto postaction;
}
}
}
else
set_free_with_pinuse(p, psize, next);
insert_chunk(fm, p, psize);
check_free_chunk(fm, p);
goto postaction;
}
}
erroraction:
USAGE_ERROR_ACTION(fm, p);
postaction:
POSTACTION(fm);
}
}
#if !FOOTERS
#undef fm
#endif /* FOOTERS */
}
 
void* dlcalloc(size_t n_elements, size_t elem_size) {
void* mem;
size_t req = 0;
if (n_elements != 0) {
req = n_elements * elem_size;
if (((n_elements | elem_size) & ~(size_t)0xffff) &&
(req / n_elements != elem_size))
req = MAX_SIZE_T; /* force downstream failure on overflow */
}
mem = dlmalloc(req);
if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
memset(mem, 0, req);
return mem;
}
 
void* dlrealloc(void* oldmem, size_t bytes) {
if (oldmem == 0)
return dlmalloc(bytes);
#ifdef REALLOC_ZERO_BYTES_FREES
if (bytes == 0) {
dlfree(oldmem);
return 0;
}
#endif /* REALLOC_ZERO_BYTES_FREES */
else {
#if ! FOOTERS
mstate m = gm;
#else /* FOOTERS */
mstate m = get_mstate_for(mem2chunk(oldmem));
if (!ok_magic(m)) {
USAGE_ERROR_ACTION(m, oldmem);
return 0;
}
#endif /* FOOTERS */
return internal_realloc(m, oldmem, bytes);
}
}
 
void* dlmemalign(size_t alignment, size_t bytes) {
return internal_memalign(gm, alignment, bytes);
}
 
void** dlindependent_calloc(size_t n_elements, size_t elem_size,
void* chunks[]) {
size_t sz = elem_size; /* serves as 1-element array */
return ialloc(gm, n_elements, &sz, 3, chunks);
}
 
void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
void* chunks[]) {
return ialloc(gm, n_elements, sizes, 0, chunks);
}
 
void* dlvalloc(size_t bytes) {
size_t pagesz;
init_mparams();
pagesz = mparams.page_size;
return dlmemalign(pagesz, bytes);
}
 
void* dlpvalloc(size_t bytes) {
size_t pagesz;
init_mparams();
pagesz = mparams.page_size;
return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
}
 
int dlmalloc_trim(size_t pad) {
int result = 0;
if (!PREACTION(gm)) {
result = sys_trim(gm, pad);
POSTACTION(gm);
}
return result;
}
 
size_t dlmalloc_footprint(void) {
return gm->footprint;
}
 
size_t dlmalloc_max_footprint(void) {
return gm->max_footprint;
}
 
#if !NO_MALLINFO
struct mallinfo dlmallinfo(void) {
return internal_mallinfo(gm);
}
#endif /* NO_MALLINFO */
 
void dlmalloc_stats() {
internal_malloc_stats(gm);
}
 
size_t dlmalloc_usable_size(void* mem) {
if (mem != 0) {
mchunkptr p = mem2chunk(mem);
if (cinuse(p))
return chunksize(p) - overhead_for(p);
}
return 0;
}
 
int dlmallopt(int param_number, int value) {
return change_mparam(param_number, value);
}
 
#endif /* !ONLY_MSPACES */
 
/* ----------------------------- user mspaces ---------------------------- */
 
#if MSPACES
 
static mstate init_user_mstate(char* tbase, size_t tsize) {
size_t msize = pad_request(sizeof(struct malloc_state));
mchunkptr mn;
mchunkptr msp = align_as_chunk(tbase);
mstate m = (mstate)(chunk2mem(msp));
memset(m, 0, msize);
INITIAL_LOCK(&m->mutex);
msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
m->seg.base = m->least_addr = tbase;
m->seg.size = m->footprint = m->max_footprint = tsize;
m->magic = mparams.magic;
m->mflags = mparams.default_mflags;
disable_contiguous(m);
init_bins(m);
mn = next_chunk(mem2chunk(m));
init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
check_top_chunk(m, m->top);
return m;
}
 
mspace create_mspace(size_t capacity, int locked) {
mstate m = 0;
size_t msize = pad_request(sizeof(struct malloc_state));
init_mparams(); /* Ensure pagesize etc initialized */
 
if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
size_t rs = ((capacity == 0)? mparams.granularity :
(capacity + TOP_FOOT_SIZE + msize));
size_t tsize = granularity_align(rs);
char* tbase = (char*)(CALL_MMAP(tsize));
if (tbase != CMFAIL) {
m = init_user_mstate(tbase, tsize);
m->seg.sflags = IS_MMAPPED_BIT;
set_lock(m, locked);
}
}
return (mspace)m;
}
 
mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
mstate m = 0;
size_t msize = pad_request(sizeof(struct malloc_state));
init_mparams(); /* Ensure pagesize etc initialized */
 
if (capacity > msize + TOP_FOOT_SIZE &&
capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
m = init_user_mstate((char*)base, capacity);
m->seg.sflags = EXTERN_BIT;
set_lock(m, locked);
}
return (mspace)m;
}
 
size_t destroy_mspace(mspace msp) {
size_t freed = 0;
mstate ms = (mstate)msp;
if (ok_magic(ms)) {
msegmentptr sp = &ms->seg;
while (sp != 0) {
char* base = sp->base;
size_t size = sp->size;
flag_t flag = sp->sflags;
sp = sp->next;
if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
CALL_MUNMAP(base, size) == 0)
freed += size;
}
}
else {
USAGE_ERROR_ACTION(ms,ms);
}
return freed;
}
 
/*
mspace versions of routines are near-clones of the global
versions. This is not so nice but better than the alternatives.
*/
 
 
void* mspace_malloc(mspace msp, size_t bytes) {
mstate ms = (mstate)msp;
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
return 0;
}
if (!PREACTION(ms)) {
void* mem;
size_t nb;
if (bytes <= MAX_SMALL_REQUEST) {
bindex_t idx;
binmap_t smallbits;
nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
idx = small_index(nb);
smallbits = ms->smallmap >> idx;
 
if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
mchunkptr b, p;
idx += ~smallbits & 1; /* Uses next bin if idx empty */
b = smallbin_at(ms, idx);
p = b->fd;
assert(chunksize(p) == small_index2size(idx));
unlink_first_small_chunk(ms, b, p, idx);
set_inuse_and_pinuse(ms, p, small_index2size(idx));
mem = chunk2mem(p);
check_malloced_chunk(ms, mem, nb);
goto postaction;
}
 
else if (nb > ms->dvsize) {
if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
mchunkptr b, p, r;
size_t rsize;
bindex_t i;
binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
binmap_t leastbit = least_bit(leftbits);
compute_bit2idx(leastbit, i);
b = smallbin_at(ms, i);
p = b->fd;
assert(chunksize(p) == small_index2size(i));
unlink_first_small_chunk(ms, b, p, i);
rsize = small_index2size(i) - nb;
/* Fit here cannot be remainderless if 4byte sizes */
if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
set_inuse_and_pinuse(ms, p, small_index2size(i));
else {
set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
r = chunk_plus_offset(p, nb);
set_size_and_pinuse_of_free_chunk(r, rsize);
replace_dv(ms, r, rsize);
}
mem = chunk2mem(p);
check_malloced_chunk(ms, mem, nb);
goto postaction;
}
 
else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
check_malloced_chunk(ms, mem, nb);
goto postaction;
}
}
}
else if (bytes >= MAX_REQUEST)
nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
else {
nb = pad_request(bytes);
if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
check_malloced_chunk(ms, mem, nb);
goto postaction;
}
}
 
if (nb <= ms->dvsize) {
size_t rsize = ms->dvsize - nb;
mchunkptr p = ms->dv;
if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
ms->dvsize = rsize;
set_size_and_pinuse_of_free_chunk(r, rsize);
set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
}
else { /* exhaust dv */
size_t dvs = ms->dvsize;
ms->dvsize = 0;
ms->dv = 0;
set_inuse_and_pinuse(ms, p, dvs);
}
mem = chunk2mem(p);
check_malloced_chunk(ms, mem, nb);
goto postaction;
}
 
else if (nb < ms->topsize) { /* Split top */
size_t rsize = ms->topsize -= nb;
mchunkptr p = ms->top;
mchunkptr r = ms->top = chunk_plus_offset(p, nb);
r->head = rsize | PINUSE_BIT;
set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
mem = chunk2mem(p);
check_top_chunk(ms, ms->top);
check_malloced_chunk(ms, mem, nb);
goto postaction;
}
 
mem = sys_alloc(ms, nb);
 
postaction:
POSTACTION(ms);
return mem;
}
 
return 0;
}
 
void mspace_free(mspace msp, void* mem) {
if (mem != 0) {
mchunkptr p = mem2chunk(mem);
#if FOOTERS
mstate fm = get_mstate_for(p);
#else /* FOOTERS */
mstate fm = (mstate)msp;
#endif /* FOOTERS */
if (!ok_magic(fm)) {
USAGE_ERROR_ACTION(fm, p);
return;
}
if (!PREACTION(fm)) {
check_inuse_chunk(fm, p);
if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
size_t psize = chunksize(p);
mchunkptr next = chunk_plus_offset(p, psize);
if (!pinuse(p)) {
size_t prevsize = p->prev_foot;
if ((prevsize & IS_MMAPPED_BIT) != 0) {
prevsize &= ~IS_MMAPPED_BIT;
psize += prevsize + MMAP_FOOT_PAD;
if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
fm->footprint -= psize;
goto postaction;
}
else {
mchunkptr prev = chunk_minus_offset(p, prevsize);
psize += prevsize;
p = prev;
if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
if (p != fm->dv) {
unlink_chunk(fm, p, prevsize);
}
else if ((next->head & INUSE_BITS) == INUSE_BITS) {
fm->dvsize = psize;
set_free_with_pinuse(p, psize, next);
goto postaction;
}
}
else
goto erroraction;
}
}
 
if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
if (!cinuse(next)) { /* consolidate forward */
if (next == fm->top) {
size_t tsize = fm->topsize += psize;
fm->top = p;
p->head = tsize | PINUSE_BIT;
if (p == fm->dv) {
fm->dv = 0;
fm->dvsize = 0;
}
if (should_trim(fm, tsize))
sys_trim(fm, 0);
goto postaction;
}
else if (next == fm->dv) {
size_t dsize = fm->dvsize += psize;
fm->dv = p;
set_size_and_pinuse_of_free_chunk(p, dsize);
goto postaction;
}
else {
size_t nsize = chunksize(next);
psize += nsize;
unlink_chunk(fm, next, nsize);
set_size_and_pinuse_of_free_chunk(p, psize);
if (p == fm->dv) {
fm->dvsize = psize;
goto postaction;
}
}
}
else
set_free_with_pinuse(p, psize, next);
insert_chunk(fm, p, psize);
check_free_chunk(fm, p);
goto postaction;
}
}
erroraction:
USAGE_ERROR_ACTION(fm, p);
postaction:
POSTACTION(fm);
}
}
}
 
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
void* mem;
size_t req = 0;
mstate ms = (mstate)msp;
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
return 0;
}
if (n_elements != 0) {
req = n_elements * elem_size;
if (((n_elements | elem_size) & ~(size_t)0xffff) &&
(req / n_elements != elem_size))
req = MAX_SIZE_T; /* force downstream failure on overflow */
}
mem = internal_malloc(ms, req);
if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
memset(mem, 0, req);
return mem;
}
 
void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
if (oldmem == 0)
return mspace_malloc(msp, bytes);
#ifdef REALLOC_ZERO_BYTES_FREES
if (bytes == 0) {
mspace_free(msp, oldmem);
return 0;
}
#endif /* REALLOC_ZERO_BYTES_FREES */
else {
#if FOOTERS
mchunkptr p = mem2chunk(oldmem);
mstate ms = get_mstate_for(p);
#else /* FOOTERS */
mstate ms = (mstate)msp;
#endif /* FOOTERS */
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
return 0;
}
return internal_realloc(ms, oldmem, bytes);
}
}
 
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
mstate ms = (mstate)msp;
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
return 0;
}
return internal_memalign(ms, alignment, bytes);
}
 
void** mspace_independent_calloc(mspace msp, size_t n_elements,
size_t elem_size, void* chunks[]) {
size_t sz = elem_size; /* serves as 1-element array */
mstate ms = (mstate)msp;
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
return 0;
}
return ialloc(ms, n_elements, &sz, 3, chunks);
}
 
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
size_t sizes[], void* chunks[]) {
mstate ms = (mstate)msp;
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
return 0;
}
return ialloc(ms, n_elements, sizes, 0, chunks);
}
 
int mspace_trim(mspace msp, size_t pad) {
int result = 0;
mstate ms = (mstate)msp;
if (ok_magic(ms)) {
if (!PREACTION(ms)) {
result = sys_trim(ms, pad);
POSTACTION(ms);
}
}
else {
USAGE_ERROR_ACTION(ms,ms);
}
return result;
}
 
void mspace_malloc_stats(mspace msp) {
mstate ms = (mstate)msp;
if (ok_magic(ms)) {
internal_malloc_stats(ms);
}
else {
USAGE_ERROR_ACTION(ms,ms);
}
}
 
size_t mspace_footprint(mspace msp) {
size_t result;
mstate ms = (mstate)msp;
if (ok_magic(ms)) {
result = ms->footprint;
}
USAGE_ERROR_ACTION(ms,ms);
return result;
}
 
 
size_t mspace_max_footprint(mspace msp) {
size_t result;
mstate ms = (mstate)msp;
if (ok_magic(ms)) {
result = ms->max_footprint;
}
USAGE_ERROR_ACTION(ms,ms);
return result;
}
 
 
#if !NO_MALLINFO
struct mallinfo mspace_mallinfo(mspace msp) {
mstate ms = (mstate)msp;
if (!ok_magic(ms)) {
USAGE_ERROR_ACTION(ms,ms);
}
return internal_mallinfo(ms);
}
#endif /* NO_MALLINFO */
 
int mspace_mallopt(int param_number, int value) {
return change_mparam(param_number, value);
}
 
#endif /* MSPACES */
 
/* -------------------- Alternative MORECORE functions ------------------- */
 
/*
Guidelines for creating a custom version of MORECORE:
 
* For best performance, MORECORE should allocate in multiples of pagesize.
* MORECORE may allocate more memory than requested. (Or even less,
but this will usually result in a malloc failure.)
* MORECORE must not allocate memory when given argument zero, but
instead return one past the end address of memory from previous
nonzero call.
* For best performance, consecutive calls to MORECORE with positive
arguments should return increasing addresses, indicating that
space has been contiguously extended.
* Even though consecutive calls to MORECORE need not return contiguous
addresses, it must be OK for malloc'ed chunks to span multiple
regions in those cases where they do happen to be contiguous.
* MORECORE need not handle negative arguments -- it may instead
just return MFAIL when given negative arguments.
Negative arguments are always multiples of pagesize. MORECORE
must not misinterpret negative args as large positive unsigned
args. You can suppress all such calls from even occurring by defining
MORECORE_CANNOT_TRIM,
 
As an example alternative MORECORE, here is a custom allocator
kindly contributed for pre-OSX macOS. It uses virtually but not
necessarily physically contiguous non-paged memory (locked in,
present and won't get swapped out). You can use it by uncommenting
this section, adding some #includes, and setting up the appropriate
defines above:
 
#define MORECORE osMoreCore
 
There is also a shutdown routine that should somehow be called for
cleanup upon program exit.
 
#define MAX_POOL_ENTRIES 100
#define MINIMUM_MORECORE_SIZE (64 * 1024U)
static int next_os_pool;
void *our_os_pools[MAX_POOL_ENTRIES];
 
void *osMoreCore(int size)
{
void *ptr = 0;
static void *sbrk_top = 0;
 
if (size > 0)
{
if (size < MINIMUM_MORECORE_SIZE)
size = MINIMUM_MORECORE_SIZE;
if (CurrentExecutionLevel() == kTaskLevel)
ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
if (ptr == 0)
{
return (void *) MFAIL;
}
// save ptrs so they can be freed during cleanup
our_os_pools[next_os_pool] = ptr;
next_os_pool++;
ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
sbrk_top = (char *) ptr + size;
return ptr;
}
else if (size < 0)
{
// we don't currently support shrink behavior
return (void *) MFAIL;
}
else
{
return sbrk_top;
}
}
 
// cleanup any allocated memory pools
// called as last thing before shutting down driver
 
void osCleanupMem(void)
{
void **ptr;
 
for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
if (*ptr)
{
PoolDeallocate(*ptr);
*ptr = 0;
}
}
 
*/
 
 
/* -----------------------------------------------------------------------
History:
V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee)
* Add max_footprint functions
* Ensure all appropriate literals are size_t
* Fix conditional compilation problem for some #define settings
* Avoid concatenating segments with the one provided
in create_mspace_with_base
* Rename some variables to avoid compiler shadowing warnings
* Use explicit lock initialization.
* Better handling of sbrk interference.
* Simplify and fix segment insertion, trimming and mspace_destroy
* Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
* Thanks especially to Dennis Flanagan for help on these.
 
V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee)
* Fix memalign brace error.
 
V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee)
* Fix improper #endif nesting in C++
* Add explicit casts needed for C++
 
V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee)
* Use trees for large bins
* Support mspaces
* Use segments to unify sbrk-based and mmap-based system allocation,
removing need for emulation on most platforms without sbrk.
* Default safety checks
* Optional footer checks. Thanks to William Robertson for the idea.
* Internal code refactoring
* Incorporate suggestions and platform-specific changes.
Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
Aaron Bachmann, Emery Berger, and others.
* Speed up non-fastbin processing enough to remove fastbins.
* Remove useless cfree() to avoid conflicts with other apps.
* Remove internal memcpy, memset. Compilers handle builtins better.
* Remove some options that no one ever used and rename others.
 
V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
* Fix malloc_state bitmap array misdeclaration
 
V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee)
* Allow tuning of FIRST_SORTED_BIN_SIZE
* Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
* Better detection and support for non-contiguousness of MORECORE.
Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
* Bypass most of malloc if no frees. Thanks To Emery Berger.
* Fix freeing of old top non-contiguous chunk im sysmalloc.
* Raised default trim and map thresholds to 256K.
* Fix mmap-related #defines. Thanks to Lubos Lunak.
* Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
* Branch-free bin calculation
* Default trim and mmap thresholds now 256K.
 
V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee)
* Introduce independent_comalloc and independent_calloc.
Thanks to Michael Pachos for motivation and help.
* Make optional .h file available
* Allow > 2GB requests on 32bit systems.
* new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
and Anonymous.
* Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
helping test this.)
* memalign: check alignment arg
* realloc: don't try to shift chunks backwards, since this
leads to more fragmentation in some programs and doesn't
seem to help in any others.
* Collect all cases in malloc requiring system memory into sysmalloc
* Use mmap as backup to sbrk
* Place all internal state in malloc_state
* Introduce fastbins (although similar to 2.5.1)
* Many minor tunings and cosmetic improvements
* Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
* Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
* Include errno.h to support default failure action.
 
V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
* return null for negative arguments
* Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
* Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
(e.g. WIN32 platforms)
* Cleanup header file inclusion for WIN32 platforms
* Cleanup code to avoid Microsoft Visual C++ compiler complaints
* Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
memory allocation routines
* Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
* Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
usage of 'assert' in non-WIN32 code
* Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
avoid infinite loop
* Always call 'fREe()' rather than 'free()'
 
V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
* Fixed ordering problem with boundary-stamping
 
V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
* Added pvalloc, as recommended by H.J. Liu
* Added 64bit pointer support mainly from Wolfram Gloger
* Added anonymously donated WIN32 sbrk emulation
* Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
* malloc_extend_top: fix mask error that caused wastage after
foreign sbrks
* Add linux mremap support code from HJ Liu
 
V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
* Integrated most documentation with the code.
* Add support for mmap, with help from
Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Use last_remainder in more cases.
* Pack bins using idea from colin@nyx10.cs.du.edu
* Use ordered bins instead of best-fit threshhold
* Eliminate block-local decls to simplify tracing and debugging.
* Support another case of realloc via move into top
* Fix error occuring when initial sbrk_base not word-aligned.
* Rely on page size for units instead of SBRK_UNIT to
avoid surprises about sbrk alignment conventions.
* Add mallinfo, mallopt. Thanks to Raymond Nijssen
(raymond@es.ele.tue.nl) for the suggestion.
* Add `pad' argument to malloc_trim and top_pad mallopt parameter.
* More precautions for cases where other routines call sbrk,
courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Added macros etc., allowing use in linux libc from
H.J. Lu (hjl@gnu.ai.mit.edu)
* Inverted this history list
 
V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
* Re-tuned and fixed to behave more nicely with V2.6.0 changes.
* Removed all preallocation code since under current scheme
the work required to undo bad preallocations exceeds
the work saved in good cases for most test programs.
* No longer use return list or unconsolidated bins since
no scheme using them consistently outperforms those that don't
given above changes.
* Use best fit for very large chunks to prevent some worst-cases.
* Added some support for debugging
 
V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
* Removed footers when chunks are in use. Thanks to
Paul Wilson (wilson@cs.texas.edu) for the suggestion.
 
V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
* Added malloc_trim, with help from Wolfram Gloger
(wmglo@Dent.MED.Uni-Muenchen.DE).
 
V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
 
V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
* realloc: try to expand in both directions
* malloc: swap order of clean-bin strategy;
* realloc: only conditionally expand backwards
* Try not to scavenge used bins
* Use bin counts as a guide to preallocation
* Occasionally bin return list chunks in first scan
* Add a few optimizations from colin@nyx10.cs.du.edu
 
V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
* faster bin computation & slightly different binning
* merged all consolidations to one part of malloc proper
(eliminating old malloc_find_space & malloc_clean_bin)
* Scan 2 returns chunks (not just 1)
* Propagate failure in realloc if malloc returns 0
* Add stuff to allow compilation on non-ANSI compilers
from kpv@research.att.com
 
V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
* removed potential for odd address access in prev_chunk
* removed dependency on getpagesize.h
* misc cosmetics and a bit more internal documentation
* anticosmetics: mangled names in macros to evade debugger strangeness
* tested on sparc, hp-700, dec-mips, rs6000
with gcc & native cc (hp, dec only) allowing
Detlefs & Zorn comparison study (in SIGPLAN Notices.)
 
Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
* Based loosely on libg++-1.2X malloc. (It retains some of the overall
structure of old version, but most details differ.)
*/
 
/** @}
*/
 
/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,13 → 46,12
#include <ipc/ipc.h>
#include <as.h>
#include <assert.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <adt/hash_table.h>
#include <mem.h>
#include <futex.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
 
/** Lock protecting the device connection list */
static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
static futex_t dcl_lock = FUTEX_INITIALIZER;
/** Device connection list head. */
static LIST_INITIALIZE(dcl_head);
 
60,20 → 59,17
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)
 
typedef struct {
fibril_mutex_t lock;
futex_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;
dev_handle_t dev_handle;
int dev_handle;
int dev_phone;
fibril_mutex_t com_area_lock;
void *com_area;
size_t com_size;
void *bb_buf;
82,22 → 78,19
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;
 
fibril_mutex_lock(&dcl_lock);
futex_down(&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) {
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
return devcon;
}
}
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
return NULL;
}
 
114,7 → 107,6
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;
122,25 → 114,25
devcon->bb_size = 0;
devcon->cache = NULL;
 
fibril_mutex_lock(&dcl_lock);
futex_down(&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) {
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
free(devcon);
return EEXIST;
}
}
list_append(&devcon->link, &dcl_head);
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
return EOK;
}
 
static void devcon_remove(devcon_t *devcon)
{
fibril_mutex_lock(&dcl_lock);
futex_down(&dcl_lock);
list_remove(&devcon->link);
fibril_mutex_unlock(&dcl_lock);
futex_up(&dcl_lock);
}
 
int block_init(dev_handle_t dev_handle, size_t com_size)
154,8 → 146,9
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;
214,16 → 207,14
if (!bb_buf)
return ENOMEM;
fibril_mutex_lock(&devcon->com_area_lock);
rc = read_block(devcon, 0, size);
off_t bufpos = 0;
size_t buflen = 0;
rc = block_read(dev_handle, &bufpos, &buflen, &off,
bb_buf, size, 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;
259,8 → 250,7
.remove_callback = cache_remove_callback
};
 
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks,
enum cache_mode mode)
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks)
{
devcon_t *devcon = devcon_search(dev_handle);
cache_t *cache;
272,12 → 262,10
if (!cache)
return ENOMEM;
fibril_mutex_initialize(&cache->lock);
futex_initialize(&cache->lock, 1);
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)) {
289,23 → 277,17
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)
{
fibril_mutex_initialize(&b->lock);
futex_initialize(&b->lock, 1);
b->refcnt = 1;
b->dirty = false;
fibril_rwlock_initialize(&b->contents_lock);
rwlock_initialize(&b->contents_lock);
link_initialize(&b->free_link);
link_initialize(&b->hash_link);
}
327,7 → 309,6
block_t *b;
link_t *l;
unsigned long key = boff;
bn_t oboff;
devcon = devcon_search(dev_handle);
 
335,7 → 316,7
assert(devcon->cache);
cache = devcon->cache;
fibril_mutex_lock(&cache->lock);
futex_down(&cache->lock);
l = hash_table_find(&cache->block_hash, &key);
if (l) {
/*
342,16 → 323,19
* We found the block in the cache.
*/
b = hash_table_get_instance(l, block_t, hash_link);
fibril_mutex_lock(&b->lock);
futex_down(&b->lock);
if (b->refcnt++ == 0)
list_remove(&b->free_link);
fibril_mutex_unlock(&b->lock);
fibril_mutex_unlock(&cache->lock);
futex_up(&b->lock);
futex_up(&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)) {
368,7 → 352,6
free(b);
goto recycle;
}
cache->blocks_cached++;
} else {
/*
* Try to recycle a block from the free list.
378,9 → 361,8
assert(!list_empty(&cache->free_head));
l = cache->free_head.next;
list_remove(l);
b = list_get_instance(l, block_t, free_link);
b = hash_table_get_instance(l, block_t, hash_link);
sync = b->dirty;
oboff = b->boff;
temp_key = b->boff;
hash_table_remove(&cache->block_hash, &temp_key, 1);
}
396,8 → 378,8
* kill concurent operations on the cache while doing I/O on the
* block.
*/
fibril_mutex_lock(&b->lock);
fibril_mutex_unlock(&cache->lock);
futex_down(&b->lock);
futex_up(&cache->lock);
 
if (sync) {
/*
404,11 → 386,7
* The block is dirty and needs to be written back to
* the device before we can read in the new contents.
*/
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);
abort(); /* TODO: block_write() */
}
if (!(flags & BLOCK_FLAGS_NOREAD)) {
/*
415,14 → 393,12
* The block contains old or no data. We need to read
* the new contents from the device.
*/
fibril_mutex_lock(&devcon->com_area_lock);
rc = read_block(devcon, b->boff, cache->block_size);
rc = block_read(dev_handle, &bufpos, &buflen, &pos,
b->data, cache->block_size, cache->block_size);
assert(rc == EOK);
memcpy(b->data, devcon->com_area, cache->block_size);
fibril_mutex_unlock(&devcon->com_area_lock);
}
 
fibril_mutex_unlock(&b->lock);
futex_up(&b->lock);
}
return b;
}
437,62 → 413,25
{
devcon_t *devcon = devcon_search(block->dev_handle);
cache_t *cache;
int rc;
 
assert(devcon);
assert(devcon->cache);
 
cache = devcon->cache;
fibril_mutex_lock(&cache->lock);
fibril_mutex_lock(&block->lock);
futex_down(&cache->lock);
futex_down(&block->lock);
if (!--block->refcnt) {
/*
* Last reference to the block was dropped. Either free the
* block or put it on the free list.
* Last reference to the block was dropped, put the block 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;
}
}
fibril_mutex_unlock(&block->lock);
fibril_mutex_unlock(&cache->lock);
futex_up(&block->lock);
futex_up(&cache->lock);
}
 
/** Read sequential data from a block device.
/** Read 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
506,8 → 445,9
*
* @return EOK on success or a negative return code on failure.
*/
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)
int
block_read(int 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;
514,7 → 454,6
devcon_t *devcon = devcon_search(dev_handle);
assert(devcon);
fibril_mutex_lock(&devcon->com_area_lock);
while (left > 0) {
size_t rd;
535,70 → 474,21
left -= rd;
}
if (*bufpos == (off_t) *buflen) {
if (*bufpos == *buflen) {
/* Refill the communication buffer with a new block. */
int rc;
 
rc = read_block(devcon, *pos / block_size, block_size);
if (rc != EOK) {
fibril_mutex_unlock(&devcon->com_area_lock);
return rc;
}
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);
*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,9 → 39,10
 
#include <stdint.h>
#include "../../srv/vfs/vfs.h"
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
 
/*
* Flags that can be used with block_get().
62,14 → 63,14
typedef unsigned bn_t; /**< Block number type. */
 
typedef struct block {
/** Mutex protecting the reference count. */
fibril_mutex_t lock;
/** Futex protecting the reference count. */
futex_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. */
fibril_rwlock_t contents_lock;
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. */
84,14 → 85,6
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);
 
98,13 → 91,12
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, enum cache_mode);
extern int block_cache_init(dev_handle_t, size_t, unsigned);
 
extern block_t *block_get(dev_handle_t, bn_t, int);
extern block_t *block_get(dev_handle_t, bn_t, int flags);
extern void block_put(block_t *);
 
extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *,
size_t, size_t);
extern int block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
 
#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/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(__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
 
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."
#endif
} parts __attribute__ ((packed));
} float32;
 
} float32;
typedef union {
double d;
uint64_t binary;
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
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."
#endif
} parts __attribute__ ((packed));
} float64;
} parts __attribute__ ((packed));
} float64;
 
#define FLOAT32_MAX 0x7f800000
#define FLOAT32_MIN 0xff800000
109,5 → 109,7
 
#endif
 
/** @}
 
/** @}
*/
 
/branches/dynload/uspace/srv/bd/file_bd/file_bd.c
File deleted
/branches/dynload/uspace/srv/bd/file_bd/Makefile
File deleted
/branches/dynload/uspace/srv/bd/rd/rd.c
File deleted
/branches/dynload/uspace/srv/bd/rd/Makefile
File deleted
/branches/dynload/uspace/srv/bd/gxe_bd/gxe_bd.c
File deleted
/branches/dynload/uspace/srv/bd/gxe_bd/Makefile
File deleted
/branches/dynload/uspace/srv/bd/ata_bd/ata_bd.c
File deleted
/branches/dynload/uspace/srv/bd/ata_bd/Makefile
File deleted
/branches/dynload/uspace/srv/bd/ata_bd/ata_bd.h
File deleted
/branches/dynload/uspace/srv/cir/fhc/Makefile
File deleted
/branches/dynload/uspace/srv/cir/fhc/fhc.c
File deleted
/branches/dynload/uspace/srv/cir/obio/Makefile
File deleted
/branches/dynload/uspace/srv/cir/obio/obio.c
File deleted
Property changes:
Deleted: svn:mergeinfo
/branches/dynload/uspace/srv/cir/obio
Property changes:
Deleted: svn:mergeinfo
/branches/dynload/uspace/srv/console/gfx/cons_idle.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/cons_kernel.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/anim_1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/anim_2.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/anim_3.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/cons_has_data.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/anim_4.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/cons_selected.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/nameic.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/gfx/helenos.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/console.c
27,7 → 27,7
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
36,72 → 36,99
#include <fb.h>
#include <ipc/ipc.h>
#include <kbd.h>
#include <io/keycode.h>
#include <kbd/keycode.h>
#include <ipc/fb.h>
#include <ipc/services.h>
#include <errno.h>
#include <keybuffer.h>
#include <key_buffer.h>
#include <ipc/console.h>
#include <unistd.h>
#include <async.h>
#include <adt/fifo.h>
#include <libadt/fifo.h>
#include <screenbuffer.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <sysinfo.h>
#include <event.h>
#include <devmap.h>
#include <fibril_sync.h>
 
#include "console.h"
#include "gcons.h"
#include "screenbuffer.h"
 
#define NAME "console"
#define MAX_KEYREQUESTS_BUFFERED 32
 
#define MAX_DEVICE_NAME 32
#define NAME "console"
 
/** Index of currently used virtual console.
*/
int active_console = 0;
int prev_console = 0;
 
/** Phone to the keyboard driver. */
static int kbd_phone;
 
/** Information about framebuffer */
struct {
int phone; /**< Framebuffer phone */
ipcarg_t cols; /**< Framebuffer columns */
ipcarg_t rows; /**< Framebuffer rows */
int color_cap; /**< Color capabilities (FB_CCAP_xxx) */
int phone; /**< Framebuffer phone */
ipcarg_t rows; /**< Framebuffer rows */
ipcarg_t cols; /**< Framebuffer columns */
} fb_info;
 
typedef struct {
size_t index; /**< Console index */
size_t refcount; /**< Connection reference count */
dev_handle_t dev_handle; /**< Device handle */
keybuffer_t keybuffer; /**< Buffer for incoming keys. */
screenbuffer_t scr; /**< Screenbuffer for saving screen
contents and related settings. */
} console_t;
keybuffer_t keybuffer; /**< Buffer for incoming keys. */
/** Buffer for unsatisfied request for keys. */
FIFO_CREATE_STATIC(keyrequests, ipc_callid_t,
MAX_KEYREQUESTS_BUFFERED);
int keyrequest_counter; /**< Number of requests in buffer. */
int client_phone; /**< Phone to connected client. */
int used; /**< 1 if this virtual console is
* connected to some client.*/
screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen
* contents and related settings. */
} connection_t;
 
/** Array of data for virtual consoles */
static console_t consoles[CONSOLE_COUNT];
static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual
* consoles */
static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared
* with framebufer used for
* faster virtual console
* switching */
 
static console_t *active_console = &consoles[0];
static console_t *prev_console = &consoles[0];
static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
 
/** Pointer to memory shared with framebufer used for
faster virtual console switching */
static keyfield_t *interbuffer = NULL;
 
/** Information on row-span yet unsent to FB driver. */
struct {
size_t col; /**< Leftmost column of the span. */
size_t row; /**< Row where the span lies. */
size_t cnt; /**< Width of the span. */
int row; /**< Row where the span lies. */
int col; /**< Leftmost column of the span. */
int n; /**< Width of the span. */
} fb_pending;
 
static FIBRIL_MUTEX_INITIALIZE(input_mutex);
static FIBRIL_CONDVAR_INITIALIZE(input_cv);
/** Size of cwrite_buf. */
#define CWRITE_BUF_SIZE 256
 
/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
static char cwrite_buf[CWRITE_BUF_SIZE];
 
static void fb_putchar(wchar_t c, int row, int col);
 
 
/** Find unused virtual console.
*
*/
static int find_free_connection(void)
{
int i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (!connections[i].used)
return i;
}
return -1;
}
 
static void clrscr(void)
{
async_msg_0(fb_info.phone, FB_CLEAR);
}
 
static void curs_visibility(bool visible)
{
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
112,16 → 139,11
ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
}
 
static void curs_goto(size_t x, size_t y)
static void curs_goto(int row, int col)
{
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
}
 
static void screen_clear(void)
{
async_msg_0(fb_info.phone, FB_CLEAR);
}
 
static void screen_yield(void)
{
ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
144,7 → 166,7
 
static void set_style(int style)
{
async_msg_1(fb_info.phone, FB_SET_STYLE, style);
async_msg_1(fb_info.phone, FB_SET_STYLE, style);
}
 
static void set_color(int fgcolor, int bgcolor, int flags)
163,10 → 185,12
case at_style:
set_style(attrs->a.s.style);
break;
 
case at_idx:
set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
attrs->a.i.flags);
break;
 
case at_rgb:
set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
break;
173,45 → 197,58
}
}
 
static int ccap_fb_to_con(int ccap_fb, int *ccap_con)
/** Send an area of screenbuffer to the FB driver. */
static void fb_update_area(connection_t *conn, int x, int y, int w, int h)
{
switch (ccap_fb) {
case FB_CCAP_NONE: *ccap_con = CONSOLE_CCAP_NONE; break;
case FB_CCAP_STYLE: *ccap_con = CONSOLE_CCAP_STYLE; break;
case FB_CCAP_INDEXED: *ccap_con = CONSOLE_CCAP_INDEXED; break;
case FB_CCAP_RGB: *ccap_con = CONSOLE_CCAP_RGB; break;
default: return EINVAL;
}
int i, j;
int rc;
attrs_t *attrs;
keyfield_t *field;
 
return EOK;
}
 
/** Send an area of screenbuffer to the FB driver. */
static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)
{
if (interbuffer) {
ipcarg_t x;
ipcarg_t y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
interbuffer[y * width + x] =
*get_field_at(&cons->scr, x0 + x, y0 + y);
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
interbuffer[i + j * w] =
*get_field_at(&conn->screenbuffer,
x + i, y + j);
}
}
async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
x0, y0, width, height);
 
rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
x, y, w, h);
} else {
rc = ENOTSUP;
}
 
if (rc != 0) {
/*
attrs = &conn->screenbuffer.attrs;
 
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
field = get_field_at(&conn->screenbuffer,
x + i, y + j);
if (!attrs_same(*attrs, field->attrs))
set_attrs(&field->attrs);
attrs = &field->attrs;
 
fb_putchar(field->character, y + j, x + i);
}
}*/
}
}
 
/** Flush pending cells to FB. */
static void fb_pending_flush(void)
{
if (fb_pending.cnt > 0) {
fb_update_area(active_console, fb_pending.col,
fb_pending.row, fb_pending.cnt, 1);
fb_pending.cnt = 0;
screenbuffer_t *scr;
 
scr = &(connections[active_console].screenbuffer);
 
if (fb_pending.n > 0) {
fb_update_area(&connections[active_console], fb_pending.col,
fb_pending.row, fb_pending.n, 1);
fb_pending.n = 0;
}
}
 
219,94 → 256,100
*
* This adds the cell to the pending rowspan if possible. Otherwise
* the old span is flushed first.
*
*/
static void cell_mark_changed(size_t col, size_t row)
static void cell_mark_changed(int row, int col)
{
if (fb_pending.cnt != 0) {
if ((col != fb_pending.col + fb_pending.cnt)
|| (row != fb_pending.row)) {
if (fb_pending.n != 0) {
if (row != fb_pending.row ||
col != fb_pending.col + fb_pending.n) {
fb_pending_flush();
}
}
if (fb_pending.cnt == 0) {
 
if (fb_pending.n == 0) {
fb_pending.row = row;
fb_pending.col = col;
fb_pending.row = row;
}
fb_pending.cnt++;
 
++fb_pending.n;
}
 
 
/** Print a character to the active VC with buffering. */
static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)
static void fb_putchar(wchar_t c, int row, int col)
{
async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
}
 
/** Process a character from the client (TTY emulation). */
static void write_char(console_t *cons, wchar_t ch)
static void write_char(int console, wchar_t ch)
{
bool flush_cursor = false;
screenbuffer_t *scr = &(connections[console].screenbuffer);
 
switch (ch) {
case '\n':
fb_pending_flush();
flush_cursor = true;
cons->scr.position_y++;
cons->scr.position_x = 0;
scr->position_y++;
scr->position_x = 0;
break;
case '\r':
break;
case '\t':
cons->scr.position_x += 8;
cons->scr.position_x -= cons->scr.position_x % 8;
scr->position_x += 8;
scr->position_x -= scr->position_x % 8;
break;
case '\b':
if (cons->scr.position_x == 0)
if (scr->position_x == 0)
break;
cons->scr.position_x--;
if (cons == active_console)
cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
screenbuffer_putchar(&cons->scr, ' ');
scr->position_x--;
if (console == active_console)
cell_mark_changed(scr->position_y, scr->position_x);
screenbuffer_putchar(scr, ' ');
break;
default:
if (cons == active_console)
cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
screenbuffer_putchar(&cons->scr, ch);
cons->scr.position_x++;
default:
if (console == active_console)
cell_mark_changed(scr->position_y, scr->position_x);
 
screenbuffer_putchar(scr, ch);
scr->position_x++;
}
if (cons->scr.position_x >= cons->scr.size_x) {
 
if (scr->position_x >= scr->size_x) {
flush_cursor = true;
cons->scr.position_y++;
scr->position_y++;
}
if (cons->scr.position_y >= cons->scr.size_y) {
if (scr->position_y >= scr->size_y) {
fb_pending_flush();
cons->scr.position_y = cons->scr.size_y - 1;
screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
if (cons == active_console)
scr->position_y = scr->size_y - 1;
screenbuffer_clear_line(scr, scr->top_line);
scr->top_line = (scr->top_line + 1) % scr->size_y;
if (console == active_console)
async_msg_1(fb_info.phone, FB_SCROLL, 1);
}
 
if (cons == active_console && flush_cursor)
curs_goto(cons->scr.position_x, cons->scr.position_y);
cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
scr->position_x = scr->position_x % scr->size_x;
 
if (console == active_console && flush_cursor)
curs_goto(scr->position_y, scr->position_x);
}
 
/** Switch to new console */
static void change_console(console_t *cons)
static void change_console(int newcons)
{
if (cons == active_console)
connection_t *conn;
int i, j, rc;
keyfield_t *field;
attrs_t *attrs;
if (newcons == active_console)
return;
 
fb_pending_flush();
if (cons == kernel_console) {
 
if (newcons == KERNEL_CONSOLE) {
async_serialize_start();
curs_hide_sync();
gcons_in_kernel();
313,68 → 356,69
screen_yield();
kbd_yield();
async_serialize_end();
 
if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
prev_console = active_console;
active_console = kernel_console;
active_console = KERNEL_CONSOLE;
} else
cons = active_console;
newcons = active_console;
}
if (cons != kernel_console) {
size_t x;
size_t y;
int rc = 0;
if (newcons != KERNEL_CONSOLE) {
async_serialize_start();
if (active_console == kernel_console) {
if (active_console == KERNEL_CONSOLE) {
screen_reclaim();
kbd_reclaim();
gcons_redraw_console();
}
active_console = cons;
gcons_change_console(cons->index);
active_console = newcons;
gcons_change_console(newcons);
conn = &connections[active_console];
set_attrs(&cons->scr.attrs);
set_attrs(&conn->screenbuffer.attrs);
curs_visibility(false);
if (interbuffer) {
for (y = 0; y < cons->scr.size_y; y++) {
for (x = 0; x < cons->scr.size_x; x++) {
interbuffer[y * cons->scr.size_x + x] =
*get_field_at(&cons->scr, x, y);
for (j = 0; j < conn->screenbuffer.size_y; j++) {
for (i = 0; i < conn->screenbuffer.size_x; i++) {
unsigned int size_x;
size_x = conn->screenbuffer.size_x;
interbuffer[j * size_x + i] =
*get_field_at(&conn->screenbuffer, i, j);
}
}
/* This call can preempt, but we are already at the end */
rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
0, 0, cons->scr.size_x,
cons->scr.size_y);
0, 0, conn->screenbuffer.size_x,
conn->screenbuffer.size_y);
}
if ((!interbuffer) || (rc != 0)) {
set_attrs(&cons->scr.attrs);
screen_clear();
set_attrs(&conn->screenbuffer.attrs);
clrscr();
attrs = &conn->screenbuffer.attrs;
for (y = 0; y < cons->scr.size_y; y++)
for (x = 0; x < cons->scr.size_x; x++) {
keyfield_t *field = get_field_at(&cons->scr, x, y);
if (!attrs_same(cons->scr.attrs, field->attrs))
for (j = 0; j < conn->screenbuffer.size_y; j++)
for (i = 0; i < conn->screenbuffer.size_x; i++) {
field = get_field_at(&conn->screenbuffer, i, j);
if (!attrs_same(*attrs, field->attrs))
set_attrs(&field->attrs);
cons->scr.attrs = field->attrs;
attrs = &field->attrs;
if ((field->character == ' ') &&
(attrs_same(field->attrs, cons->scr.attrs)))
(attrs_same(field->attrs,
conn->screenbuffer.attrs)))
continue;
fb_putchar(field->character, x, y);
 
fb_putchar(field->character, j, i);
}
}
curs_goto(cons->scr.position_x, cons->scr.position_y);
curs_visibility(cons->scr.is_cursor_visible);
curs_goto(conn->screenbuffer.position_y,
conn->screenbuffer.position_x);
curs_visibility(conn->screenbuffer.is_cursor_visible);
async_serialize_end();
}
383,19 → 427,31
/** Handler for keyboard */
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
{
/* Ignore parameters, the connection is already opened */
while (true) {
ipc_call_t call;
ipc_callid_t callid = async_get_call(&call);
int retval;
console_event_t ev;
ipc_callid_t callid;
ipc_call_t call;
int retval;
kbd_event_t ev;
connection_t *conn;
int newcon;
/* Ignore parameters, the connection is alread opened */
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/* TODO: Handle hangup */
return;
case KBD_MS_LEFT:
newcon = gcons_mouse_btn(IPC_GET_ARG1(call));
if (newcon != -1)
change_console(newcon);
retval = 0;
break;
case KBD_MS_MOVE:
gcons_mouse_move(IPC_GET_ARG1(call),
IPC_GET_ARG2(call));
retval = 0;
break;
case KBD_EVENT:
/* Got event from keyboard driver. */
retval = 0;
404,19 → 460,30
ev.mods = IPC_GET_ARG3(call);
ev.c = IPC_GET_ARG4(call);
/* switch to another virtual console */
conn = &connections[active_console];
 
if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
if (ev.key == KC_F1 + KERNEL_CONSOLE)
change_console(kernel_console);
if (ev.key == KC_F12)
change_console(KERNEL_CONSOLE);
else
change_console(&consoles[ev.key - KC_F1]);
change_console(ev.key - KC_F1);
break;
}
fibril_mutex_lock(&input_mutex);
keybuffer_push(&active_console->keybuffer, &ev);
fibril_condvar_broadcast(&input_cv);
fibril_mutex_unlock(&input_mutex);
/* if client is awaiting key, send it */
if (conn->keyrequest_counter > 0) {
conn->keyrequest_counter--;
ipc_answer_4(fifo_pop(conn->keyrequests), EOK,
ev.type, ev.key, ev.mods, ev.c);
break;
}
 
keybuffer_push(&conn->keybuffer, &ev);
retval = 0;
 
break;
default:
retval = ENOENT;
425,135 → 492,67
}
}
 
static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
/** Handle CONSOLE_WRITE call. */
static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t size;
wchar_t ch;
size_t off;
 
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *buf = (char *) malloc(size);
if (buf == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
(void) ipc_data_write_finalize(callid, buf, size);
 
if (size > CWRITE_BUF_SIZE)
size = CWRITE_BUF_SIZE;
 
(void) ipc_data_write_finalize(callid, cwrite_buf, size);
 
async_serialize_start();
size_t off = 0;
 
off = 0;
while (off < size) {
wchar_t ch = str_decode(buf, &off, size);
write_char(cons, ch);
ch = str_decode(cwrite_buf, &off, size);
write_char(consnum, ch);
}
 
async_serialize_end();
gcons_notify_char(cons->index);
 
gcons_notify_char(consnum);
ipc_answer_1(rid, EOK, size);
free(buf);
}
 
static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *buf = (char *) malloc(size);
if (buf == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
size_t pos = 0;
console_event_t ev;
fibril_mutex_lock(&input_mutex);
recheck:
while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
if (ev.type == KEY_PRESS) {
buf[pos] = ev.c;
pos++;
}
}
if (pos == size) {
(void) ipc_data_read_finalize(callid, buf, size);
ipc_answer_1(rid, EOK, size);
free(buf);
} else {
fibril_condvar_wait(&input_cv, &input_mutex);
goto recheck;
}
fibril_mutex_unlock(&input_mutex);
}
 
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
{
console_event_t ev;
 
fibril_mutex_lock(&input_mutex);
recheck:
if (keybuffer_pop(&cons->keybuffer, &ev)) {
ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
} else {
fibril_condvar_wait(&input_cv, &input_mutex);
goto recheck;
}
fibril_mutex_unlock(&input_mutex);
}
 
/** Default thread for new connections */
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
console_t *cons = NULL;
ipc_callid_t callid;
ipc_call_t call;
int consnum;
ipcarg_t arg1, arg2, arg3, arg4;
connection_t *conn;
screenbuffer_t *scr;
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (i == KERNEL_CONSOLE)
continue;
if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {
cons = &consoles[i];
break;
}
}
if (cons == NULL) {
ipc_answer_0(iid, ENOENT);
if ((consnum = find_free_connection()) == -1) {
ipc_answer_0(iid, ELIMIT);
return;
}
conn = &connections[consnum];
conn->used = 1;
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t arg1;
ipcarg_t arg2;
ipcarg_t arg3;
 
int cons_ccap;
int rc;
async_serialize_start();
if (cons->refcount == 0)
gcons_notify_connect(cons->index);
gcons_notify_connect(consnum);
conn->client_phone = IPC_GET_ARG5(*icall);
screenbuffer_clear(&conn->screenbuffer);
if (consnum == active_console)
clrscr();
cons->refcount++;
/* Accept the connection */
ipc_answer_0(iid, EOK);
while (true) {
while (1) {
async_serialize_end();
callid = async_get_call(&call);
async_serialize_start();
561,63 → 560,64
arg1 = 0;
arg2 = 0;
arg3 = 0;
arg4 = 0;
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cons->refcount--;
if (cons->refcount == 0)
gcons_notify_disconnect(cons->index);
gcons_notify_disconnect(consnum);
/* Answer all pending requests */
while (conn->keyrequest_counter > 0) {
conn->keyrequest_counter--;
ipc_answer_0(fifo_pop(conn->keyrequests),
ENOENT);
break;
}
conn->used = 0;
return;
case VFS_OUT_READ:
case CONSOLE_PUTCHAR:
write_char(consnum, IPC_GET_ARG1(call));
gcons_notify_char(consnum);
break;
case CONSOLE_WRITE:
async_serialize_end();
cons_read(cons, callid, &call);
cons_write(consnum, callid, &call);
async_serialize_start();
continue;
case VFS_OUT_WRITE:
async_serialize_end();
cons_write(cons, callid, &call);
async_serialize_start();
continue;
case VFS_OUT_SYNC:
fb_pending_flush();
if (cons == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
curs_goto(cons->scr.position_x, cons->scr.position_y);
}
break;
case CONSOLE_CLEAR:
/* Send message to fb */
if (cons == active_console)
async_msg_0(fb_info.phone, FB_CLEAR);
if (consnum == active_console) {
async_msg_0(fb_info.phone, FB_CLEAR);
}
screenbuffer_clear(&cons->scr);
screenbuffer_clear(&conn->screenbuffer);
break;
case CONSOLE_GOTO:
screenbuffer_goto(&cons->scr,
IPC_GET_ARG1(call), IPC_GET_ARG2(call));
if (cons == active_console)
screenbuffer_goto(&conn->screenbuffer,
IPC_GET_ARG2(call), IPC_GET_ARG1(call));
if (consnum == active_console)
curs_goto(IPC_GET_ARG1(call),
IPC_GET_ARG2(call));
break;
case CONSOLE_GET_SIZE:
arg1 = fb_info.cols;
arg2 = fb_info.rows;
case CONSOLE_GETSIZE:
arg1 = fb_info.rows;
arg2 = fb_info.cols;
break;
case CONSOLE_GET_COLOR_CAP:
rc = ccap_fb_to_con(fb_info.color_cap, &cons_ccap);
if (rc != EOK) {
ipc_answer_0(callid, rc);
continue;
case CONSOLE_FLUSH:
fb_pending_flush();
if (consnum == active_console) {
async_req_0_0(fb_info.phone, FB_FLUSH);
 
scr = &(connections[consnum].screenbuffer);
curs_goto(scr->position_y, scr->position_x);
}
arg1 = cons_ccap;
break;
case CONSOLE_SET_STYLE:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
screenbuffer_set_style(&cons->scr, arg1);
if (cons == active_console)
screenbuffer_set_style(&conn->screenbuffer, arg1);
if (consnum == active_console)
set_style(arg1);
break;
case CONSOLE_SET_COLOR:
625,8 → 625,9
arg1 = IPC_GET_ARG1(call);
arg2 = IPC_GET_ARG2(call);
arg3 = IPC_GET_ARG3(call);
screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
if (cons == active_console)
screenbuffer_set_color(&conn->screenbuffer, arg1,
arg2, arg3);
if (consnum == active_console)
set_color(arg1, arg2, arg3);
break;
case CONSOLE_SET_RGB_COLOR:
633,27 → 634,46
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
arg2 = IPC_GET_ARG2(call);
screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
if (cons == active_console)
screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
arg2);
if (consnum == active_console)
set_rgb_color(arg1, arg2);
break;
case CONSOLE_CURSOR_VISIBILITY:
fb_pending_flush();
arg1 = IPC_GET_ARG1(call);
cons->scr.is_cursor_visible = arg1;
if (cons == active_console)
conn->screenbuffer.is_cursor_visible = arg1;
if (consnum == active_console)
curs_visibility(arg1);
break;
case CONSOLE_GET_EVENT:
async_serialize_end();
cons_get_event(cons, callid, &call);
async_serialize_start();
continue;
case CONSOLE_GETKEY:
if (keybuffer_empty(&conn->keybuffer)) {
/* buffer is empty -> store request */
if (conn->keyrequest_counter <
MAX_KEYREQUESTS_BUFFERED) {
fifo_push(conn->keyrequests, callid);
conn->keyrequest_counter++;
} else {
/*
* No key available and too many
* requests => fail.
*/
ipc_answer_0(callid, ELIMIT);
}
continue;
}
kbd_event_t ev;
keybuffer_pop(&conn->keybuffer, &ev);
arg1 = ev.type;
arg2 = ev.key;
arg3 = ev.mods;
arg4 = ev.c;
break;
case CONSOLE_KCON_ENABLE:
change_console(kernel_console);
change_console(KERNEL_CONSOLE);
break;
}
ipc_answer_3(callid, EOK, arg1, arg2, arg3);
ipc_answer_4(callid, EOK, arg1, arg2, arg3, arg4);
}
}
 
662,25 → 682,30
change_console(prev_console);
}
 
static bool console_init(void)
int main(int argc, char *argv[])
{
ipcarg_t color_cap;
 
printf(NAME ": HelenOS Console service\n");
ipcarg_t phonehash;
size_t ib_size;
int i;
async_set_client_connection(client_connection);
/* Connect to keyboard driver */
kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
if (kbd_phone < 0) {
printf(NAME ": Failed to connect to keyboard service\n");
return false;
return -1;
}
ipcarg_t phonehash;
if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
printf(NAME ": Failed to create callback from keyboard service\n");
return false;
return -1;
}
async_new_connection(phonehash, 0, NULL, keyboard_events);
 
/* Connect to framebuffer driver */
fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
if (fb_info.phone < 0) {
688,30 → 713,48
return -1;
}
/* Register driver */
int rc = devmap_driver_register(NAME, client_connection);
if (rc < 0) {
printf(NAME ": Unable to register driver (%d)\n", rc);
return false;
}
/* Disable kernel output to the console */
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Initialize gcons */
gcons_init(fb_info.phone);
/* Synchronize, the gcons could put something in queue */
/* Synchronize, the gcons can have something in queue */
async_req_0_0(fb_info.phone, FB_FLUSH);
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &color_cap);
fb_info.color_cap = color_cap;
async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
&fb_info.cols);
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
clrscr();
/* Init virtual consoles */
for (i = 0; i < CONSOLE_COUNT; i++) {
connections[i].used = 0;
keybuffer_init(&connections[i].keybuffer);
connections[i].keyrequests.head = 0;
connections[i].keyrequests.tail = 0;
connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
connections[i].keyrequest_counter = 0;
if (screenbuffer_init(&connections[i].screenbuffer,
fb_info.cols, fb_info.rows) == NULL) {
/* FIXME: handle error */
return -1;
}
}
connections[KERNEL_CONSOLE].used = 1;
 
/* Set up shared memory buffer. */
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
interbuffer = as_get_mappable_page(ib_size);
 
fb_pending.n = 0;
 
if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
interbuffer = NULL;
}
 
if (interbuffer) {
if (ipc_share_out_start(fb_info.phone, interbuffer,
AS_AREA_READ) != EOK) {
720,62 → 763,22
}
}
fb_pending.cnt = 0;
curs_goto(0, 0);
curs_visibility(
connections[active_console].screenbuffer.is_cursor_visible);
/* Inititalize consoles */
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++) {
if (i != KERNEL_CONSOLE) {
if (screenbuffer_init(&consoles[i].scr,
fb_info.cols, fb_info.rows) == NULL) {
printf(NAME ": Unable to allocate screen buffer %u\n", i);
return false;
}
screenbuffer_clear(&consoles[i].scr);
keybuffer_init(&consoles[i].keybuffer);
consoles[i].index = i;
consoles[i].refcount = 0;
char vc[MAX_DEVICE_NAME];
snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device %s\n", vc);
return false;
}
}
}
/* Register at NS */
if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
return -1;
/* Disable kernel output to the console */
__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
/* Initialize the screen */
async_serialize_start();
gcons_redraw_console();
set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
screen_clear();
curs_goto(0, 0);
curs_visibility(active_console->scr.is_cursor_visible);
async_serialize_end();
/* Receive kernel notifications */
if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
printf(NAME ": Error registering kconsole notifications\n");
async_set_interrupt_received(interrupt_received);
return true;
}
 
int main(int argc, char *argv[])
{
printf(NAME ": HelenOS Console service\n");
if (!console_init())
return -1;
printf(NAME ": Accepting connections\n");
// FIXME: avoid connectiong to itself, keep using klog
// printf(NAME ": Accepting connections\n");
async_manager();
return 0;
/branches/dynload/uspace/srv/console/screenbuffer.c
27,50 → 27,44
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
 
#include <screenbuffer.h>
#include <io/style.h>
#include <console/style.h>
#include <malloc.h>
#include <unistd.h>
 
/** Store one character to screenbuffer.
/** Store one character to screenbuffer. Its position is determined by
* scr->position_x and scr->position_y.
*
* Its position is determined by scr->position_x
* and scr->position_y.
*
* @param scr Screenbuffer
* @param c Stored character
*
* @param scr screenbuffer
* @param c stored character
*/
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t ch)
{
keyfield_t *field =
get_field_at(scr, scr->position_x, scr->position_y);
keyfield_t *field;
 
field = get_field_at(scr, scr->position_x, scr->position_y);
 
field->character = ch;
field->attrs = scr->attrs;
}
 
/** Initilize screenbuffer.
*
* Allocate space for screen content in accordance to given size.
*
* @param scr Initialized screenbuffer
* @param size_x Width in characters
* @param size_y Height in characters
*
* @return Pointer to screenbuffer (same as scr parameter) or NULL
*
/** Initilize screenbuffer. Allocate space for screen content in accordance to given size.
* @param scr initialized screenbuffer
* @param size_x width in characters
* @param size_y height in characters
* @return pointer to screenbuffer (same as scr parameter) or NULL
*/
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y)
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y)
{
scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y);
if (!scr->buffer)
if (!scr->buffer) {
return NULL;
}
scr->size_x = size_x;
scr->size_y = size_y;
83,63 → 77,56
return scr;
}
 
/** Clear screenbuffer.
*
* @param scr Screenbuffer
*
/** Clear screenbuffer.
* @param scr screenbuffer
*/
void screenbuffer_clear(screenbuffer_t *scr)
{
size_t i;
unsigned int i;
for (i = 0; i < (scr->size_x * scr->size_y); i++) {
scr->buffer[i].character = ' ';
scr->buffer[i].attrs = scr->attrs;
}
 
scr->top_line = 0;
scr->position_y = 0;
scr->position_x = 0;
scr->position_y = 0;
}
 
/** Clear one buffer line.
*
* @param scr
* @param line One buffer line (not a screen line!)
*
*/
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line)
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line)
{
size_t x;
unsigned int i;
for (x = 0; x < scr->size_x; x++) {
scr->buffer[x + line * scr->size_x].character = ' ';
scr->buffer[x + line * scr->size_x].attrs = scr->attrs;
for (i = 0; i < scr->size_x; i++) {
scr->buffer[i + line * scr->size_x].character = ' ';
scr->buffer[i + line * scr->size_x].attrs = scr->attrs;
}
}
 
/** Copy content buffer from screenbuffer to given memory.
*
* @param scr Source screenbuffer
* @param dest Destination
*
* @param scr source screenbuffer
* @param dest destination
*/
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest)
{
size_t i;
unsigned int i;
for (i = 0; i < (scr->size_x * scr->size_y); i++)
for (i = 0; i < scr->size_x * scr->size_y; i++) {
dest[i] = scr->buffer[i];
}
}
 
/** Set new cursor position in screenbuffer.
*
* @param scr
* @param x
* @param y
*
*/
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y)
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y)
{
scr->position_x = x % scr->size_x;
scr->position_y = y % scr->size_y;
146,13 → 133,11
}
 
/** Set new style.
*
* @param scr
* @param fg_color
* @param bg_color
*
*/
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style)
void screenbuffer_set_style(screenbuffer_t *scr, int style)
{
scr->attrs.t = at_style;
scr->attrs.a.s.style = style;
159,13 → 144,11
}
 
/** Set new color.
*
* @param scr
* @param fg_color
* @param bg_color
*
*/
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags)
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color, unsigned int flags)
{
scr->attrs.t = at_idx;
scr->attrs.a.i.fg_color = fg_color;
174,13 → 157,11
}
 
/** Set new RGB color.
*
* @param scr
* @param fg_color
* @param bg_color
*
*/
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color)
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color)
{
scr->attrs.t = at_rgb;
scr->attrs.a.r.fg_color = fg_color;
187,5 → 168,6
scr->attrs.a.r.bg_color = bg_color;
}
 
/** @}
*/
/branches/dynload/uspace/srv/console/screenbuffer.h
27,20 → 27,19
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
 
#ifndef SCREENBUFFER_H__
#define SCREENBUFFER_H__
#ifndef __SCREENBUFFER_H__
#define __SCREENBUFFER_H__
 
#include <stdint.h>
#include <sys/types.h>
#include <bool.h>
 
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
#define DEFAULT_FOREGROUND 0x0 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0xf0f0f0 /**< default console background color */
 
typedef struct {
uint8_t style;
53,8 → 52,8
} attr_idx_t;
 
typedef struct {
uint32_t bg_color; /**< background color */
uint32_t fg_color; /**< foreground color */
uint32_t bg_color; /**< background color */
uint32_t fg_color; /**< foreground color */
} attr_rgb_t;
 
typedef struct {
67,93 → 66,73
attr_style_t s;
attr_idx_t i;
attr_rgb_t r;
} a;
} a;
} attrs_t;
 
/** One field on screen. It contain one character and its attributes. */
typedef struct {
wchar_t character; /**< Character itself */
attrs_t attrs; /**< Character attributes */
wchar_t character; /**< Character itself */
attrs_t attrs; /**< Character`s attributes */
} keyfield_t;
 
/** Structure for buffering state of one virtual console.
*/
typedef struct {
keyfield_t *buffer; /**< Screen content - characters and
their attributes (used as a circular buffer) */
size_t size_x; /**< Number of columns */
size_t size_y; /**< Number of rows */
/** Coordinates of last printed character for determining cursor position */
size_t position_x;
size_t position_y;
attrs_t attrs; /**< Current attributes. */
size_t top_line; /**< Points to buffer[][] line that will
be printed at screen as the first line */
bool is_cursor_visible; /**< Cursor state - default is visible */
keyfield_t *buffer; /**< Screen content - characters and their attributes. Used as a circular buffer. */
unsigned int size_x, size_y; /**< Number of columns and rows */
unsigned int position_x, position_y; /**< Coordinates of last printed character for determining cursor position */
attrs_t attrs; /**< Current attributes. */
unsigned int top_line; /**< Points to buffer[][] line that will be printed at screen as the first line */
unsigned char is_cursor_visible; /**< Cursor state - default is visible */
} screenbuffer_t;
 
/** Returns keyfield for position on screen
*
* Screenbuffer->buffer is cyclic buffer so we
* must couted in index of the topmost line.
*
* @param scr Screenbuffer
* @param x Position on screen
* @param y Position on screen
*
* @return Keyfield structure with character and its attributes on x, y
*
/** Returns keyfield for position on screen. Screenbuffer->buffer is cyclic buffer so we must couted in index of the topmost line.
* @param scr screenbuffer
* @param x position on screen
* @param y position on screen
* @return keyfield structure with character and its attributes on x,y
*/
static inline keyfield_t *get_field_at(screenbuffer_t *scr, size_t x, size_t y)
static inline keyfield_t *get_field_at(screenbuffer_t *scr, unsigned int x, unsigned int y)
{
return scr->buffer + x + ((y + scr->top_line) % scr->size_y) * scr->size_x;
}
 
/** Compares two sets of attributes.
*
* @param s1 First style
* @param s2 Second style
*
* @return Nonzero on equality
*
* @param s1 first style
* @param s2 second style
* @return nonzero on equality
*/
static inline int attrs_same(attrs_t a1, attrs_t a2)
{
if (a1.t != a2.t)
return 0;
if (a1.t != a2.t) return 0;
 
switch (a1.t) {
case at_style:
return (a1.a.s.style == a2.a.s.style);
case at_idx:
return (a1.a.i.fg_color == a2.a.i.fg_color)
&& (a1.a.i.bg_color == a2.a.i.bg_color)
&& (a1.a.i.flags == a2.a.i.flags);
case at_rgb:
return (a1.a.r.fg_color == a2.a.r.fg_color)
&& (a1.a.r.bg_color == a2.a.r.bg_color);
case at_style: return a1.a.s.style == a2.a.s.style;
case at_idx: return a1.a.i.fg_color == a2.a.i.fg_color &&
a1.a.i.bg_color == a2.a.i.bg_color &&
a1.a.i.flags == a2.a.i.flags;
case at_rgb: return a1.a.r.fg_color == a2.a.r.fg_color &&
a1.a.r.bg_color == a2.a.r.bg_color;
}
return 0;
}
 
 
void screenbuffer_putchar(screenbuffer_t *scr, wchar_t c);
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y);
screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, int size_x, int size_y);
 
void screenbuffer_clear(screenbuffer_t *scr);
void screenbuffer_clear_line(screenbuffer_t *scr, size_t line);
void screenbuffer_clear_line(screenbuffer_t *scr, unsigned int line);
void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest);
void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y);
void screenbuffer_set_style(screenbuffer_t *scr, uint8_t style);
void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color,
uint8_t bg_color, uint8_t attr);
void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color,
uint32_t bg_color);
void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y);
void screenbuffer_set_style(screenbuffer_t *scr, int style);
void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color,
unsigned int bg_color, unsigned int attr);
void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color,
unsigned int bg_color);
 
#endif
 
/** @}
*/
 
/branches/dynload/uspace/srv/console/Makefile
42,29 → 42,23
#
 
OUTPUT = console
 
GENERIC_SOURCES = \
console.c \
screenbuffer.c \
../kbd/generic/keybuffer.c \
../kbd/generic/key_buffer.c \
gcons.c
 
IMAGES = \
gfx/helenos.ppm \
gfx/nameic.ppm \
gfx/cons_selected.ppm \
gfx/cons_idle.ppm \
gfx/cons_has_data.ppm \
gfx/cons_kernel.ppm \
gfx/anim_1.ppm \
gfx/anim_2.ppm \
gfx/anim_3.ppm \
gfx/anim_4.ppm
IMAGES = helenos.ppm nameic.ppm cons_selected.ppm cons_idle.ppm \
cons_has_data.ppm cons_kernel.ppm anim_1.ppm anim_2.ppm anim_3.ppm \
anim_4.ppm
 
ARCH_SOURCES =
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) \
$(addsuffix .o,$(basename $(IMAGES)))
$(addsuffix .o,$(basename $(IMAGES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
 
OBJECTS := $(GENERIC_OBJECTS)
OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS)
 
.PHONY: all clean depend disasm
 
84,7 → 78,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/console/console.h
27,7 → 27,7
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
35,10 → 35,11
#ifndef __CONSOLE_H__
#define __CONSOLE_H__
 
#define CONSOLE_COUNT 12
#define KERNEL_CONSOLE 11
#define KERNEL_CONSOLE 11
 
#define CONSOLE_COUNT 12
 
#endif
 
/** @}
*/
/branches/dynload/uspace/srv/console/gcons.c
27,7 → 27,7
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
39,25 → 39,23
#include <sys/mman.h>
#include <string.h>
#include <align.h>
#include <bool.h>
 
#include "console.h"
#include "gcons.h"
 
#define CONSOLE_TOP 66
#define CONSOLE_MARGIN 6
#define CONSOLE_TOP 66
#define CONSOLE_MARGIN 6
 
#define STATUS_START 110
#define STATUS_TOP 8
#define STATUS_SPACE 4
#define STATUS_WIDTH 48
#define STATUS_HEIGHT 48
#define STATUS_START 110
#define STATUS_TOP 8
#define STATUS_SPACE 4
#define STATUS_WIDTH 48
#define STATUS_HEIGHT 48
 
#define MAIN_COLOR 0xffffff
#define MAIN_COLOR 0xffffff
 
static bool use_gcons = false;
static ipcarg_t xres;
static ipcarg_t yres;
static int use_gcons = 0;
static ipcarg_t xres,yres;
 
enum butstate {
CONS_DISCONNECTED = 0,
79,15 → 77,8
static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
static int animation = -1;
 
static size_t active_console = 0;
static int active_console = 0;
 
size_t mouse_x;
size_t mouse_y;
 
bool btn_pressed;
size_t btn_x;
size_t btn_y;
 
static void vp_switch(int vp)
{
async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
94,7 → 85,8
}
 
/** Create view port */
static int vp_create(size_t x, size_t y, size_t width, size_t height)
static int vp_create(unsigned int x, unsigned int y, unsigned int width,
unsigned int height)
{
return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
(width << 16) | height);
105,52 → 97,48
async_msg_0(fbphone, FB_CLEAR);
}
 
static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
static void set_rgb_color(int fgcolor, int bgcolor)
{
async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
}
 
/** Transparent putchar */
static void tran_putch(wchar_t ch, size_t col, size_t row)
static void tran_putch(char c, int row, int col)
{
async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
async_msg_3(fbphone, FB_PUTCHAR, c, row, col);
}
 
/** Redraw the button showing state of a given console */
static void redraw_state(size_t index)
static void redraw_state(int consnum)
{
vp_switch(cstatus_vp[index]);
enum butstate state = console_state[index];
char data[5];
int i;
enum butstate state = console_state[consnum];
 
vp_switch(cstatus_vp[consnum]);
if (ic_pixmaps[state] != -1)
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum],
ic_pixmaps[state]);
if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
&& (state != CONS_DISCONNECTED_SEL)) {
char data[5];
snprintf(data, 5, "%u", index + 1);
size_t i;
for (i = 0; data[i] != 0; i++)
tran_putch(data[i], 2 + i, 1);
}
 
if (state != CONS_DISCONNECTED && state != CONS_KERNEL &&
state != CONS_DISCONNECTED_SEL) {
snprintf(data, 5, "%d", consnum + 1);
for (i = 0; data[i]; i++)
tran_putch(data[i], 1, 2 + i);
}
}
 
/** Notification run on changing console (except kernel console) */
void gcons_change_console(size_t index)
void gcons_change_console(int consnum)
{
int i;
 
if (!use_gcons)
return;
 
if (active_console == KERNEL_CONSOLE) {
size_t i;
for (i = 0; i < CONSOLE_COUNT; i++)
redraw_state(i);
if (animation != -1)
async_msg_1(fbphone, FB_ANIM_START, animation);
} else {
158,74 → 146,71
console_state[active_console] = CONS_DISCONNECTED;
else
console_state[active_console] = CONS_IDLE;
redraw_state(active_console);
}
active_console = index;
if ((console_state[index] == CONS_DISCONNECTED)
|| (console_state[index] == CONS_DISCONNECTED_SEL))
console_state[index] = CONS_DISCONNECTED_SEL;
else
console_state[index] = CONS_SELECTED;
redraw_state(index);
active_console = consnum;
 
if (console_state[consnum] == CONS_DISCONNECTED) {
console_state[consnum] = CONS_DISCONNECTED_SEL;
redraw_state(consnum);
} else
console_state[consnum] = CONS_SELECTED;
redraw_state(consnum);
 
vp_switch(console_vp);
}
 
/** Notification function that gets called on new output to virtual console */
void gcons_notify_char(size_t index)
void gcons_notify_char(int consnum)
{
if (!use_gcons)
return;
if ((index == active_console)
|| (console_state[index] == CONS_HAS_DATA))
 
if (consnum == active_console ||
console_state[consnum] == CONS_HAS_DATA)
return;
console_state[index] = CONS_HAS_DATA;
 
console_state[consnum] = CONS_HAS_DATA;
 
if (active_console == KERNEL_CONSOLE)
return;
 
redraw_state(consnum);
redraw_state(index);
vp_switch(console_vp);
}
 
/** Notification function called on service disconnect from console */
void gcons_notify_disconnect(size_t index)
void gcons_notify_disconnect(int consnum)
{
if (!use_gcons)
return;
if (index == active_console)
console_state[index] = CONS_DISCONNECTED_SEL;
if (active_console == consnum)
console_state[consnum] = CONS_DISCONNECTED_SEL;
else
console_state[index] = CONS_DISCONNECTED;
console_state[consnum] = CONS_DISCONNECTED;
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(index);
redraw_state(consnum);
vp_switch(console_vp);
}
 
/** Notification function called on console connect */
void gcons_notify_connect(size_t index)
void gcons_notify_connect(int consnum)
{
if (!use_gcons)
return;
if (index == active_console)
console_state[index] = CONS_SELECTED;
if (active_console == consnum)
console_state[consnum] = CONS_SELECTED;
else
console_state[index] = CONS_IDLE;
console_state[consnum] = CONS_IDLE;
 
if (active_console == KERNEL_CONSOLE)
return;
redraw_state(index);
 
redraw_state(consnum);
vp_switch(console_vp);
}
 
239,28 → 224,29
vp_switch(0);
}
 
/** Return x, where left <= x <= right && |a-x| == min(|a-x|) is smallest */
static inline int limit(size_t a, size_t left, size_t right)
/** Return x, where left <= x <= right && |a-x|==min(|a-x|) is smallest */
static inline int limit(int a,int left, int right)
{
if (a < left)
a = left;
if (a >= right)
a = right - 1;
return a;
}
 
int mouse_x, mouse_y;
int btn_pressed, btn_x, btn_y;
 
/** Handle mouse move
*
* @param dx Delta X of mouse move
* @param dy Delta Y of mouse move
*/
void gcons_mouse_move(ssize_t dx, ssize_t dy)
void gcons_mouse_move(int dx, int dy)
{
mouse_x = limit(mouse_x + dx, 0, xres);
mouse_y = limit(mouse_y + dy, 0, yres);
 
async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
}
 
267,8 → 253,8
static int gcons_find_conbut(int x, int y)
{
int status_start = STATUS_START + (xres - 800) / 2;
if ((y < STATUS_TOP) || (y >= STATUS_TOP + STATUS_HEIGHT))
 
if (y < STATUS_TOP || y >= STATUS_TOP + STATUS_HEIGHT)
return -1;
if (x < status_start)
284,31 → 270,28
 
/** Handle mouse click
*
* @param state New state (true - pressed, false - depressed)
* @param state New state (1-pressed, 0-depressed)
*/
int gcons_mouse_btn(bool state)
int gcons_mouse_btn(int state)
{
int conbut;
 
if (state) {
conbut = gcons_find_conbut(mouse_x, mouse_y);
if (conbut != -1) {
btn_pressed = true;
btn_pressed = 1;
btn_x = mouse_x;
btn_y = mouse_y;
}
return -1;
}
if ((!state) && (!btn_pressed))
}
if (!state && !btn_pressed)
return -1;
btn_pressed = false;
btn_pressed = 0;
 
conbut = gcons_find_conbut(mouse_x, mouse_y);
if (conbut == gcons_find_conbut(btn_x, btn_y))
return conbut;
return -1;
}
 
324,40 → 307,35
{
char *shm;
int rc;
 
/* Create area */
shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
MAP_ANONYMOUS, 0, 0);
if (shm == MAP_FAILED)
return;
 
memcpy(shm, logo, size);
/* Send area */
rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
if (rc)
goto exit;
rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
if (rc)
goto drop;
/* Draw logo */
async_msg_2(fbphone, FB_DRAW_PPM, x, y);
drop:
/* Drop area */
async_msg_0(fbphone, FB_DROP_SHM);
exit:
exit:
/* Remove area */
munmap(shm, size);
}
 
extern char _binary_gfx_helenos_ppm_start[0];
extern int _binary_gfx_helenos_ppm_size;
extern char _binary_gfx_nameic_ppm_start[0];
extern int _binary_gfx_nameic_ppm_size;
extern char _binary_helenos_ppm_start[0];
extern int _binary_helenos_ppm_size;
extern char _binary_nameic_ppm_start[0];
extern int _binary_nameic_ppm_size;
 
/** Redraws console graphics */
void gcons_redraw_console(void)
370,14 → 348,13
vp_switch(0);
set_rgb_color(MAIN_COLOR, MAIN_COLOR);
clear();
draw_pixmap(_binary_gfx_helenos_ppm_start,
(size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2);
draw_pixmap(_binary_gfx_nameic_ppm_start,
(size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
draw_pixmap(_binary_helenos_ppm_start,
(size_t) &_binary_helenos_ppm_size, xres - 66, 2);
draw_pixmap(_binary_nameic_ppm_start,
(size_t) &_binary_nameic_ppm_size, 5, 17);
for (i = 0; i < CONSOLE_COUNT; i++)
redraw_state(i);
vp_switch(console_vp);
}
 
385,102 → 362,102
*
* @param data PPM data
* @param size PPM data size
*
* @return Pixmap identification
*
*/
static int make_pixmap(char *data, size_t size)
static int make_pixmap(char *data, int size)
{
char *shm;
int rc;
int pxid = -1;
 
/* Create area */
shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
MAP_ANONYMOUS, 0, 0);
if (shm == MAP_FAILED)
return -1;
 
memcpy(shm, data, size);
/* Send area */
rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (ipcarg_t) shm);
if (rc)
goto exit;
rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
if (rc)
goto drop;
 
/* Obtain pixmap */
rc = async_req_0_0(fbphone, FB_SHM2PIXMAP);
if (rc < 0)
goto drop;
pxid = rc;
drop:
/* Drop area */
async_msg_0(fbphone, FB_DROP_SHM);
exit:
exit:
/* Remove area */
munmap(shm, size);
 
return pxid;
}
 
extern char _binary_gfx_anim_1_ppm_start[0];
extern int _binary_gfx_anim_1_ppm_size;
extern char _binary_gfx_anim_2_ppm_start[0];
extern int _binary_gfx_anim_2_ppm_size;
extern char _binary_gfx_anim_3_ppm_start[0];
extern int _binary_gfx_anim_3_ppm_size;
extern char _binary_gfx_anim_4_ppm_start[0];
extern int _binary_gfx_anim_4_ppm_size;
extern char _binary_anim_1_ppm_start[0];
extern int _binary_anim_1_ppm_size;
extern char _binary_anim_2_ppm_start[0];
extern int _binary_anim_2_ppm_size;
extern char _binary_anim_3_ppm_start[0];
extern int _binary_anim_3_ppm_size;
extern char _binary_anim_4_ppm_start[0];
extern int _binary_anim_4_ppm_size;
 
static void make_anim(void)
{
int an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]);
int an;
int pm;
 
an = async_req_1_0(fbphone, FB_ANIM_CREATE, cstatus_vp[KERNEL_CONSOLE]);
if (an < 0)
return;
int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
(int) &_binary_gfx_anim_1_ppm_size);
 
pm = make_pixmap(_binary_anim_1_ppm_start,
(int) &_binary_anim_1_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
(int) &_binary_gfx_anim_2_ppm_size);
 
pm = make_pixmap(_binary_anim_2_ppm_start,
(int) &_binary_anim_2_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
(int) &_binary_gfx_anim_3_ppm_size);
 
pm = make_pixmap(_binary_anim_3_ppm_start,
(int) &_binary_anim_3_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
(int) &_binary_gfx_anim_4_ppm_size);
 
pm = make_pixmap(_binary_anim_4_ppm_start,
(int) &_binary_anim_4_ppm_size);
async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 
async_msg_1(fbphone, FB_ANIM_START, an);
 
animation = an;
}
 
extern char _binary_gfx_cons_selected_ppm_start[0];
extern int _binary_gfx_cons_selected_ppm_size;
extern char _binary_gfx_cons_idle_ppm_start[0];
extern int _binary_gfx_cons_idle_ppm_size;
extern char _binary_gfx_cons_has_data_ppm_start[0];
extern int _binary_gfx_cons_has_data_ppm_size;
extern char _binary_gfx_cons_kernel_ppm_start[0];
extern int _binary_gfx_cons_kernel_ppm_size;
extern char _binary_cons_selected_ppm_start[0];
extern int _binary_cons_selected_ppm_size;
extern char _binary_cons_idle_ppm_start[0];
extern int _binary_cons_idle_ppm_size;
extern char _binary_cons_has_data_ppm_start[0];
extern int _binary_cons_has_data_ppm_size;
extern char _binary_cons_kernel_ppm_start[0];
extern int _binary_cons_kernel_ppm_size;
 
/** Initialize nice graphical console environment */
void gcons_init(int phone)
{
int rc;
int i;
int status_start = STATUS_START;
fbphone = phone;
int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
if (rc)
return;
487,27 → 464,22
if ((xres < 800) || (yres < 600))
return;
/* Create console viewport */
/* create console viewport */
/* Align width & height to character size */
console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
ALIGN_DOWN(xres - 2 * CONSOLE_MARGIN, 8),
ALIGN_DOWN(yres - (CONSOLE_TOP + CONSOLE_MARGIN), 16));
if (console_vp < 0)
return;
/* Create status buttons */
size_t status_start = STATUS_START + (xres - 800) / 2;
size_t i;
status_start += (xres - 800) / 2;
for (i = 0; i < CONSOLE_COUNT; i++) {
cstatus_vp[i] = vp_create(status_start + CONSOLE_MARGIN +
i * (STATUS_WIDTH + STATUS_SPACE), STATUS_TOP,
STATUS_WIDTH, STATUS_HEIGHT);
if (cstatus_vp[i] < 0)
return;
vp_switch(cstatus_vp[i]);
set_rgb_color(0x202020, 0xffffff);
}
514,29 → 486,26
/* Initialize icons */
ic_pixmaps[CONS_SELECTED] =
make_pixmap(_binary_gfx_cons_selected_ppm_start,
(size_t) &_binary_gfx_cons_selected_ppm_size);
ic_pixmaps[CONS_IDLE] =
make_pixmap(_binary_gfx_cons_idle_ppm_start,
(size_t) &_binary_gfx_cons_idle_ppm_size);
make_pixmap(_binary_cons_selected_ppm_start,
(int) &_binary_cons_selected_ppm_size);
ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start,
(int) &_binary_cons_idle_ppm_size);
ic_pixmaps[CONS_HAS_DATA] =
make_pixmap(_binary_gfx_cons_has_data_ppm_start,
(size_t) &_binary_gfx_cons_has_data_ppm_size);
make_pixmap(_binary_cons_has_data_ppm_start,
(int) &_binary_cons_has_data_ppm_size);
ic_pixmaps[CONS_DISCONNECTED] =
make_pixmap(_binary_gfx_cons_idle_ppm_start,
(size_t) &_binary_gfx_cons_idle_ppm_size);
ic_pixmaps[CONS_KERNEL] =
make_pixmap(_binary_gfx_cons_kernel_ppm_start,
(size_t) &_binary_gfx_cons_kernel_ppm_size);
make_pixmap(_binary_cons_idle_ppm_start,
(int) &_binary_cons_idle_ppm_size);
ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start,
(int) &_binary_cons_kernel_ppm_size);
ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
make_anim();
use_gcons = true;
use_gcons = 1;
console_state[0] = CONS_DISCONNECTED_SEL;
console_state[KERNEL_CONSOLE] = CONS_KERNEL;
vp_switch(console_vp);
gcons_redraw_console();
}
 
/** @}
/branches/dynload/uspace/srv/console/gcons.h
27,30 → 27,25
*/
 
/** @addtogroup console
* @{
* @{
*/
/** @file
*/
 
#ifndef GCONS_H_
#define GCONS_H_
#ifndef _GCONS_H_
#define _GCONS_H_
 
#include <sys/types.h>
 
void gcons_init(int phone);
 
void gcons_redraw_console(void);
void gcons_change_console(size_t index);
void gcons_notify_char(size_t index);
void gcons_change_console(int consnum);
void gcons_notify_char(int consnum);
void gcons_in_kernel(void);
void gcons_notify_connect(int consnum);
void gcons_notify_disconnect(int consnum);
void gcons_mouse_move(int dx, int dy);
int gcons_mouse_btn(int state);
 
void gcons_notify_connect(size_t index);
void gcons_notify_disconnect(size_t index);
 
void gcons_mouse_move(ssize_t dx, ssize_t dy);
int gcons_mouse_btn(bool state);
 
#endif
 
/** @}
*/
/branches/dynload/uspace/srv/console/cons_kernel.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/anim_1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/anim_2.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/anim_3.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/anim_4.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/cons_has_data.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/cons_selected.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/cons_idle.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/nameic.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/console/helenos.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/branches/dynload/uspace/srv/rd/rd.c
0,0 → 1,311
/*
* Copyright (c) 2007 Michal Konopa
* Copyright (c) 2007 Martin Jelen
* Copyright (c) 2007 Peter Majer
* Copyright (c) 2007 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 rd
* @{
*/
 
/**
* @file rd.c
* @brief Initial RAM disk for HelenOS.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <futex.h>
#include <stdio.h>
#include <ipc/devmap.h>
#include "rd.h"
 
#define NAME "rd"
 
/** Pointer to the ramdisk's image. */
static void *rd_addr;
/** Size of the ramdisk. */
static size_t rd_size;
 
/**
* This futex protects the ramdisk's data.
* If we were to serve multiple requests (read + write or several writes)
* concurrently (i.e. from two or more threads), each read and write needs to be
* protected by this futex.
*/
atomic_t rd_futex = FUTEX_INITIALIZER;
 
/** Handle one connection to ramdisk.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
void *fs_va = NULL;
off_t offset;
size_t block_size;
size_t maxblock_size;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
/*
* Now we wait for the client to send us its communication as_area.
*/
int flags;
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) {
fs_va = as_get_mappable_page(maxblock_size);
if (fs_va) {
(void) ipc_share_out_finalize(callid, fs_va);
} else {
ipc_answer_0(callid, EHANGUP);
return;
}
} else {
/*
* The client doesn't speak the same protocol.
* At this point we can't handle protocol variations.
* Close the connection.
*/
ipc_answer_0(callid, EHANGUP);
return;
}
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/*
* The other side has hung up.
* Answer the message and exit the fibril.
*/
ipc_answer_0(callid, EOK);
return;
case RD_READ_BLOCK:
offset = IPC_GET_ARG1(call);
block_size = IPC_GET_ARG2(call);
if (block_size > maxblock_size) {
/*
* Maximum block size exceeded.
*/
retval = ELIMIT;
break;
}
if (offset * block_size > rd_size - block_size) {
/*
* Reading past the end of the device.
*/
retval = ELIMIT;
break;
}
futex_down(&rd_futex);
memcpy(fs_va, rd_addr + offset * block_size, block_size);
futex_up(&rd_futex);
retval = EOK;
break;
case RD_WRITE_BLOCK:
offset = IPC_GET_ARG1(call);
block_size = IPC_GET_ARG2(call);
if (block_size > maxblock_size) {
/*
* Maximum block size exceeded.
*/
retval = ELIMIT;
break;
}
if (offset * block_size > rd_size - block_size) {
/*
* Writing past the end of the device.
*/
retval = ELIMIT;
break;
}
futex_up(&rd_futex);
memcpy(rd_addr + offset * block_size, fs_va, block_size);
futex_down(&rd_futex);
retval = EOK;
break;
default:
/*
* The client doesn't speak the same protocol.
* Instead of closing the connection, we just ignore
* the call. This can be useful if the client uses a
* newer version of the protocol.
*/
retval = EINVAL;
break;
}
ipc_answer_0(callid, retval);
}
}
 
static int driver_register(char *name)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
if (phone < 0) {
printf(NAME ": Failed to connect to device mapper\n");
return -1;
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(phone, (char *) name, str_size(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return -1;
}
 
async_set_client_connection(rd_connection);
 
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
async_wait_for(req, &retval);
 
return phone;
}
 
static int device_register(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(driver_phone, (char *) name,
str_size(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (handle != NULL)
*handle = -1;
if (EOK == retval) {
if (NULL != handle)
*handle = (int) IPC_GET_ARG1(answer);
}
return retval;
}
 
/** Prepare the ramdisk image for operation. */
static bool rd_init(void)
{
rd_size = sysinfo_value("rd.size");
void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
if (rd_size == 0) {
printf(NAME ": No RAM disk found\n");
return false;
}
rd_addr = as_get_mappable_page(rd_size);
int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
int retval = physmem_map(rd_ph_addr, rd_addr,
ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping RAM disk\n");
return false;
}
printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size);
int driver_phone = driver_register(NAME);
if (driver_phone < 0) {
printf(NAME ": Unable to register driver\n");
return false;
}
int dev_handle;
if (EOK != device_register(driver_phone, "initrd", &dev_handle)) {
ipc_hangup(driver_phone);
printf(NAME ": Unable to register device\n");
return false;
}
 
/*
* Create the second device.
* We need at least two devices for the sake of testing of non-root
* mounts. Of course it would be better to allow the second device
* be created dynamically...
*/
if (EOK != device_register(driver_phone, "spared", &dev_handle)) {
ipc_hangup(driver_phone);
printf(NAME ": Unable to register device\n");
return false;
}
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS RAM disk server\n");
if (!rd_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
/branches/dynload/uspace/srv/rd/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 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.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = rd
SOURCES = \
rd.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dynload/uspace/srv/rd/rd.h
0,0 → 1,50
/*
* Copyright (c) 2007 Michal Konopa
* Copyright (c) 2007 Martin Jelen
* Copyright (c) 2007 Peter Majer
* Copyright (c) 2007 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 rd
* @{
*/
 
/**
* @file rd.h
* @brief Initial RAM disk for HelenOS - header
*/
 
/* Basic constants. */
 
#ifndef RD_RD_H_
#define RD_RD_H_
 
#define RD_BASE 1024
#define RD_READ_BLOCK (RD_BASE + 1) /**< Method for reading block. */
#define RD_WRITE_BLOCK (RD_BASE + 2) /**< Method for writing block. */
 
#endif
/branches/dynload/uspace/srv/fs/devfs/devfs.c
File deleted
/branches/dynload/uspace/srv/fs/devfs/devfs_ops.c
File deleted
/branches/dynload/uspace/srv/fs/devfs/devfs.h
File deleted
/branches/dynload/uspace/srv/fs/devfs/Makefile
File deleted
/branches/dynload/uspace/srv/fs/devfs/devfs_ops.h
File deleted
/branches/dynload/uspace/srv/fs/tmpfs/tmpfs.h
38,7 → 38,7
#include <atomic.h>
#include <sys/types.h>
#include <bool.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
#ifndef dprintf
#define dprintf(...) printf(__VA_ARGS__)
86,11 → 86,7
extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
 
extern bool tmpfs_restore(dev_handle_t);
 
/branches/dynload/uspace/srv/fs/tmpfs/tmpfs_dump.c
54,8 → 54,8
} __attribute__((packed));
 
static bool
tmpfs_restore_recursion(dev_handle_t dev, off_t *bufpos, size_t *buflen,
off_t *pos, fs_node_t *pfn)
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos,
fs_node_t *pfn)
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
67,8 → 67,8
tmpfs_node_t *nodep;
uint32_t size;
if (block_seqread(dev, bufpos, buflen, pos, &entry,
sizeof(entry), TMPFS_BLOCK_SIZE) != EOK)
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE) != EOK)
return false;
entry.len = uint32_t_le2host(entry.len);
87,7 → 87,7
return false;
}
if (block_seqread(dev, bufpos, buflen, pos, fname,
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy(fn);
free(fname);
103,7 → 103,7
}
free(fname);
if (block_seqread(dev, bufpos, buflen, pos, &size,
if (block_read(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE) != EOK)
return false;
115,7 → 115,7
return false;
nodep->size = size;
if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
if (block_read(dev, bufpos, buflen, pos, nodep->data,
size, TMPFS_BLOCK_SIZE) != EOK)
return false;
131,7 → 131,7
return false;
}
if (block_seqread(dev, bufpos, buflen, pos, fname,
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy(fn);
free(fname);
174,7 → 174,7
off_t pos = 0;
char tag[6];
if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5,
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE) != EOK)
goto error;
/branches/dynload/uspace/srv/fs/tmpfs/tmpfs_ops.c
47,7 → 47,7
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
#include <as.h>
#include <libfs.h>
 
250,7 → 250,6
free(nodep);
return NULL;
}
fs_node_initialize(nodep->bp);
nodep->bp->data = nodep; /* link the FS and TMPFS nodes */
if (!tmpfs_root_get(dev_handle))
nodep->index = TMPFS_SOME_ROOT;
409,7 → 408,12
 
void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t mp_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);
ipc_answer_0(rid, ENOTSUP);
}
 
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
596,11 → 600,6
ipc_answer_0(rid, EOK);
}
 
void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
623,22 → 622,6
ipc_answer_0(rid, rc);
}
 
void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
}
 
void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
{
libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
}
 
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/fs/tmpfs/tmpfs.c
96,41 → 96,27
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
return;
case VFS_OUT_MOUNTED:
case VFS_MOUNTED:
tmpfs_mounted(callid, &call);
break;
case VFS_OUT_MOUNT:
case VFS_MOUNT:
tmpfs_mount(callid, &call);
break;
case VFS_OUT_LOOKUP:
case VFS_LOOKUP:
tmpfs_lookup(callid, &call);
break;
case VFS_OUT_READ:
case VFS_READ:
tmpfs_read(callid, &call);
break;
case VFS_OUT_WRITE:
case VFS_WRITE:
tmpfs_write(callid, &call);
break;
case VFS_OUT_TRUNCATE:
case VFS_TRUNCATE:
tmpfs_truncate(callid, &call);
break;
case VFS_OUT_CLOSE:
tmpfs_close(callid, &call);
break;
case VFS_OUT_DESTROY:
case VFS_DESTROY:
tmpfs_destroy(callid, &call);
break;
case VFS_OUT_OPEN_NODE:
tmpfs_open_node(callid, &call);
break;
case VFS_OUT_STAT:
tmpfs_stat(callid, &call);
break;
case VFS_OUT_SYNC:
tmpfs_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
152,7 → 138,7
printf(NAME ": Unable to connect to VFS\n");
return -1;
}
 
int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info,
tmpfs_connection);
if (rc != EOK) {
/branches/dynload/uspace/srv/fs/tmpfs/Makefile
72,7 → 72,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/fs/fat/fat.h
35,7 → 35,6
 
#include "fat_fat.h"
#include <ipc/ipc.h>
#include <fibril_sync.h>
#include <libfs.h>
#include <atomic.h>
#include <sys/types.h>
161,7 → 160,7
/** Used indices (index) hash table link. */
link_t uih_link;
 
fibril_mutex_t lock;
futex_t lock;
dev_handle_t dev_handle;
fs_index_t index;
/**
182,7 → 181,7
/** Back pointer to the FS node. */
fs_node_t *bp;
fibril_mutex_t lock;
futex_t lock;
fat_node_type_t type;
fat_idx_t *idx;
/**
207,12 → 206,7
extern void fat_read(ipc_callid_t, ipc_call_t *);
extern void fat_write(ipc_callid_t, ipc_call_t *);
extern void fat_truncate(ipc_callid_t, ipc_call_t *);
extern void fat_stat(ipc_callid_t, ipc_call_t *);
extern void fat_close(ipc_callid_t, ipc_call_t *);
extern void fat_destroy(ipc_callid_t, ipc_call_t *);
extern void fat_open_node(ipc_callid_t, ipc_call_t *);
extern void fat_stat(ipc_callid_t, ipc_call_t *);
extern void fat_sync(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_new(dev_handle_t);
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
/branches/dynload/uspace/srv/fs/fat/fat_ops.c
48,10 → 48,10
#include <errno.h>
#include <string.h>
#include <byteorder.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <assert.h>
#include <fibril_sync.h>
#include <futex.h>
#include <sys/mman.h>
#include <align.h>
 
58,8 → 58,8
#define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL)
#define FS_NODE(node) ((node) ? (node)->bp : NULL)
 
/** Mutex protecting the list of cached free FAT nodes. */
static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
 
/** List of cached free FAT nodes. */
static LIST_INITIALIZE(ffn_head);
66,7 → 66,7
 
static void fat_node_initialize(fat_node_t *node)
{
fibril_mutex_initialize(&node->lock);
futex_initialize(&node->lock, 1);
node->bp = NULL;
node->idx = NULL;
node->type = 0;
115,30 → 115,30
fs_node_t *fn;
fat_node_t *nodep;
 
fibril_mutex_lock(&ffn_mutex);
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (!fibril_mutex_trylock(&nodep->lock))
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
goto skip_cache;
idxp_tmp = nodep->idx;
if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
fibril_mutex_unlock(&nodep->lock);
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
fibril_mutex_unlock(&ffn_mutex);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
fibril_mutex_unlock(&nodep->lock);
fibril_mutex_unlock(&idxp_tmp->lock);
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
fn = FS_NODE(nodep);
} else {
skip_cache:
/* Try to allocate a new node structure. */
fibril_mutex_unlock(&ffn_mutex);
futex_up(&ffn_futex);
fn = (fs_node_t *)malloc(sizeof(fs_node_t));
if (!fn)
return NULL;
149,7 → 149,6
}
}
fat_node_initialize(nodep);
fs_node_initialize(fn);
fn->data = nodep;
nodep->bp = fn;
175,10 → 174,10
* We are lucky.
* The node is already instantiated in memory.
*/
fibril_mutex_lock(&idxp->nodep->lock);
futex_down(&idxp->nodep->lock);
if (!idxp->nodep->refcnt++)
list_remove(&idxp->nodep->ffn_link);
fibril_mutex_unlock(&idxp->nodep->lock);
futex_up(&idxp->nodep->lock);
return idxp->nodep;
}
 
268,7 → 267,7
return NULL;
/* idxp->lock held */
nodep = fat_node_get_core(idxp);
fibril_mutex_unlock(&idxp->lock);
futex_up(&idxp->lock);
return FS_NODE(nodep);
}
 
277,12 → 276,12
fat_node_t *nodep = FAT_NODE(fn);
bool destroy = false;
 
fibril_mutex_lock(&nodep->lock);
futex_down(&nodep->lock);
if (!--nodep->refcnt) {
if (nodep->idx) {
fibril_mutex_lock(&ffn_mutex);
futex_down(&ffn_futex);
list_append(&nodep->ffn_link, &ffn_head);
fibril_mutex_unlock(&ffn_mutex);
futex_up(&ffn_futex);
} else {
/*
* The node does not have any index structure associated
293,7 → 292,7
destroy = true;
}
}
fibril_mutex_unlock(&nodep->lock);
futex_up(&nodep->lock);
if (destroy) {
free(nodep->bp);
free(nodep);
360,7 → 359,7
nodep->idx = idxp;
idxp->nodep = nodep;
 
fibril_mutex_unlock(&idxp->lock);
futex_up(&idxp->lock);
return FS_NODE(nodep);
}
 
402,7 → 401,7
fat_dentry_t *d;
fat_bs_t *bs;
block_t *b;
unsigned i, j;
int i, j;
uint16_t bps;
unsigned dps;
unsigned blocks;
409,16 → 408,16
fat_cluster_t mcl, lcl;
int rc;
 
fibril_mutex_lock(&childp->lock);
futex_down(&childp->lock);
if (childp->lnkcnt == 1) {
/*
* On FAT, we don't support multiple hard links.
*/
fibril_mutex_unlock(&childp->lock);
futex_up(&childp->lock);
return EMLINK;
}
assert(childp->lnkcnt == 0);
fibril_mutex_unlock(&childp->lock);
futex_up(&childp->lock);
 
if (!fat_dentry_name_verify(name)) {
/*
432,7 → 431,7
* a new one.
*/
fibril_mutex_lock(&parentp->idx->lock);
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
463,12 → 462,12
*/
if (parentp->idx->pfc == FAT_CLST_ROOT) {
/* Can't grow the root directory. */
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return ENOSPC;
}
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
if (rc != EOK) {
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return rc;
}
fat_append_clusters(bs, parentp, mcl);
491,9 → 490,9
fat_dentry_name_set(d, name);
b->dirty = true; /* need to sync block */
block_put(b);
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
 
fibril_mutex_lock(&childp->idx->lock);
futex_down(&childp->idx->lock);
/*
* If possible, create the Sub-directory Identifier Entry and the
529,12 → 528,12
 
childp->idx->pfc = parentp->firstc;
childp->idx->pdi = i * dps + j;
fibril_mutex_unlock(&childp->idx->lock);
futex_up(&childp->idx->lock);
 
fibril_mutex_lock(&childp->lock);
futex_down(&childp->lock);
childp->lnkcnt = 1;
childp->dirty = true; /* need to sync node */
fibril_mutex_unlock(&childp->lock);
futex_up(&childp->lock);
 
/*
* Hash in the index structure into the position hash.
559,10 → 558,10
if (fat_has_children(cfn))
return ENOTEMPTY;
 
fibril_mutex_lock(&parentp->lock);
fibril_mutex_lock(&childp->lock);
futex_down(&parentp->lock);
futex_down(&childp->lock);
assert(childp->lnkcnt == 1);
fibril_mutex_lock(&childp->idx->lock);
futex_down(&childp->idx->lock);
bs = block_bb_get(childp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
 
581,11 → 580,11
/* clear position information */
childp->idx->pfc = FAT_CLST_RES0;
childp->idx->pdi = 0;
fibril_mutex_unlock(&childp->idx->lock);
futex_up(&childp->idx->lock);
childp->lnkcnt = 0;
childp->dirty = true;
fibril_mutex_unlock(&childp->lock);
fibril_mutex_unlock(&parentp->lock);
futex_up(&childp->lock);
futex_up(&parentp->lock);
 
return EOK;
}
602,7 → 601,7
fat_dentry_t *d;
block_t *b;
 
fibril_mutex_lock(&parentp->idx->lock);
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
617,7 → 616,7
continue;
case FAT_DENTRY_LAST:
block_put(b);
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return NULL;
default:
case FAT_DENTRY_VALID:
636,7 → 635,7
fat_idx_t *idx = fat_idx_get_by_pos(
parentp->idx->dev_handle, parentp->firstc,
i * dps + j);
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
if (!idx) {
/*
* Can happen if memory is low or if we
646,7 → 645,7
return NULL;
}
nodep = fat_node_get_core(idx);
fibril_mutex_unlock(&idx->lock);
futex_up(&idx->lock);
block_put(b);
return FS_NODE(nodep);
}
654,7 → 653,7
block_put(b);
}
 
fibril_mutex_unlock(&parentp->idx->lock);
futex_up(&parentp->idx->lock);
return NULL;
}
 
686,7 → 685,7
if (nodep->type != FAT_DIRECTORY)
return false;
fibril_mutex_lock(&nodep->idx->lock);
futex_down(&nodep->idx->lock);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
705,22 → 704,22
continue;
case FAT_DENTRY_LAST:
block_put(b);
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return false;
default:
case FAT_DENTRY_VALID:
block_put(b);
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
}
 
fibril_mutex_unlock(&nodep->idx->lock);
futex_up(&nodep->idx->lock);
return false;
}
 
770,7 → 769,6
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
enum cache_mode cmode;
fat_bs_t *bs;
uint16_t bps;
uint16_t rde;
798,12 → 796,6
}
opts[size] = '\0';
 
/* Check for option enabling write through. */
if (str_cmp(opts, "wtcache") == 0)
cmode = CACHE_MODE_WT;
else
cmode = CACHE_MODE_WB;
 
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE);
if (rc != EOK) {
833,7 → 825,7
}
 
/* Initialize the block cache */
rc = block_cache_init(dev_handle, bps, 0 /* XXX */, cmode);
rc = block_cache_init(dev_handle, bps, 0 /* XXX */);
if (rc != EOK) {
block_fini(dev_handle);
ipc_answer_0(rid, rc);
855,7 → 847,6
ipc_answer_0(rid, ENOMEM);
return;
}
fs_node_initialize(rfn);
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
free(rfn);
888,7 → 879,7
rootp->bp = rfn;
rfn->data = rootp;
fibril_mutex_unlock(&ridxp->lock);
futex_up(&ridxp->lock);
 
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
}
895,7 → 886,7
 
void fat_mount(ipc_callid_t rid, ipc_call_t *request)
{
libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
ipc_answer_0(rid, ENOTSUP);
}
 
void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
1176,11 → 1167,6
return;
}
 
void fat_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
1197,22 → 1183,6
ipc_answer_0(rid, rc);
}
 
void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_stat(ipc_callid_t rid, ipc_call_t *request)
{
libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/fs/fat/fat.c
89,41 → 89,27
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
return;
case VFS_OUT_MOUNTED:
case VFS_MOUNTED:
fat_mounted(callid, &call);
break;
case VFS_OUT_MOUNT:
case VFS_MOUNT:
fat_mount(callid, &call);
break;
case VFS_OUT_LOOKUP:
case VFS_LOOKUP:
fat_lookup(callid, &call);
break;
case VFS_OUT_READ:
case VFS_READ:
fat_read(callid, &call);
break;
case VFS_OUT_WRITE:
case VFS_WRITE:
fat_write(callid, &call);
break;
case VFS_OUT_TRUNCATE:
case VFS_TRUNCATE:
fat_truncate(callid, &call);
break;
case VFS_OUT_STAT:
fat_stat(callid, &call);
break;
case VFS_OUT_CLOSE:
fat_close(callid, &call);
break;
case VFS_OUT_DESTROY:
case VFS_DESTROY:
fat_destroy(callid, &call);
break;
case VFS_OUT_OPEN_NODE:
fat_open_node(callid, &call);
break;
case VFS_OUT_SYNC:
fat_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/dynload/uspace/srv/fs/fat/Makefile
74,7 → 74,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/fs/fat/fat_idx.c
39,10 → 39,10
#include "../../vfs/vfs.h"
#include <errno.h>
#include <string.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <assert.h>
#include <fibril_sync.h>
#include <futex.h>
 
/** Each instance of this type describes one interval of freed VFS indices. */
typedef struct {
68,8 → 68,8
link_t freed_head;
} unused_t;
 
/** Mutex protecting the list of unused structures. */
static FIBRIL_MUTEX_INITIALIZE(unused_lock);
/** Futex protecting the list of unused structures. */
static futex_t unused_futex = FUTEX_INITIALIZER;
 
/** List of unused structures. */
static LIST_INITIALIZE(unused_head);
89,7 → 89,7
link_t *l;
 
if (lock)
fibril_mutex_lock(&unused_lock);
futex_down(&unused_futex);
for (l = unused_head.next; l != &unused_head; l = l->next) {
u = list_get_instance(l, unused_t, link);
if (u->dev_handle == dev_handle)
96,12 → 96,12
return u;
}
if (lock)
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return NULL;
}
 
/** Mutex protecting the up_hash and ui_hash. */
static FIBRIL_MUTEX_INITIALIZE(used_lock);
/** Futex protecting the up_hash and ui_hash. */
static futex_t used_futex = FUTEX_INITIALIZER;
 
/**
* Global hash table of all used fat_idx_t structures.
231,7 → 231,7
*/
*index = u->next++;
--u->remaining;
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return true;
}
} else {
244,7 → 244,7
list_remove(&f->link);
free(f);
}
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return true;
}
/*
252,7 → 252,7
* theoretically still possible (e.g. too many open unlinked nodes or
* too many zero-sized nodes).
*/
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return false;
}
 
302,7 → 302,7
if (lnk->prev != &u->freed_head)
try_coalesce_intervals(lnk->prev, lnk,
lnk);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return;
}
if (f->last == index - 1) {
310,7 → 310,7
if (lnk->next != &u->freed_head)
try_coalesce_intervals(lnk, lnk->next,
lnk);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return;
}
if (index > f->first) {
321,7 → 321,7
n->first = index;
n->last = index;
list_insert_before(&n->link, lnk);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return;
}
 
335,7 → 335,7
n->last = index;
list_append(&n->link, &u->freed_head);
}
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
}
 
static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
352,7 → 352,7
link_initialize(&fidx->uph_link);
link_initialize(&fidx->uih_link);
fibril_mutex_initialize(&fidx->lock);
futex_initialize(&fidx->lock, 1);
fidx->dev_handle = dev_handle;
fidx->pfc = FAT_CLST_RES0; /* no parent yet */
fidx->pdi = 0;
365,10 → 365,10
{
fat_idx_t *fidx;
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
fidx = fat_idx_create(dev_handle);
if (!fidx) {
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
return NULL;
}
378,8 → 378,8
};
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
fibril_mutex_lock(&fidx->lock);
fibril_mutex_unlock(&used_lock);
futex_down(&fidx->lock);
futex_up(&used_futex);
 
return fidx;
}
395,7 → 395,7
[UPH_PDI_KEY] = pdi,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
l = hash_table_find(&up_hash, pkey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
402,7 → 402,7
} else {
fidx = fat_idx_create(dev_handle);
if (!fidx) {
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
return NULL;
}
417,8 → 417,8
hash_table_insert(&up_hash, pkey, &fidx->uph_link);
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
}
fibril_mutex_lock(&fidx->lock);
fibril_mutex_unlock(&used_lock);
futex_down(&fidx->lock);
futex_up(&used_futex);
 
return fidx;
}
431,9 → 431,9
[UPH_PDI_KEY] = idx->pdi,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
hash_table_insert(&up_hash, pkey, &idx->uph_link);
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
}
 
void fat_idx_hashout(fat_idx_t *idx)
444,9 → 444,9
[UPH_PDI_KEY] = idx->pdi,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
hash_table_remove(&up_hash, pkey, 3);
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
}
 
fat_idx_t *
459,13 → 459,13
[UIH_INDEX_KEY] = index,
};
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
l = hash_table_find(&ui_hash, ikey);
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uih_link);
fibril_mutex_lock(&fidx->lock);
futex_down(&fidx->lock);
}
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
 
return fidx;
}
483,7 → 483,7
 
assert(idx->pfc == FAT_CLST_RES0);
 
fibril_mutex_lock(&used_lock);
futex_down(&used_futex);
/*
* Since we can only free unlinked nodes, the index structure is not
* present in the position hash (uph). We therefore hash it out from
490,7 → 490,7
* the index hash only.
*/
hash_table_remove(&ui_hash, ikey, 2);
fibril_mutex_unlock(&used_lock);
futex_up(&used_futex);
/* Release the VFS index. */
fat_index_free(idx->dev_handle, idx->index);
/* Deallocate the structure. */
524,12 → 524,12
if (!u)
return ENOMEM;
unused_initialize(u, dev_handle);
fibril_mutex_lock(&unused_lock);
futex_down(&unused_futex);
if (!unused_find(dev_handle, false))
list_append(&u->link, &unused_head);
else
rc = EEXIST;
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
return rc;
}
 
540,7 → 540,7
u = unused_find(dev_handle, true);
assert(u);
list_remove(&u->link);
fibril_mutex_unlock(&unused_lock);
futex_up(&unused_futex);
 
while (!list_empty(&u->freed_head)) {
freed_t *f;
/branches/dynload/uspace/srv/fs/fat/fat_fat.c
45,15 → 45,14
#include <byteorder.h>
#include <align.h>
#include <assert.h>
#include <fibril_sync.h>
#include <mem.h>
#include <futex.h>
 
/**
* The fat_alloc_lock mutex protects all copies of the File Allocation Table
* The fat_alloc_lock futex protects all copies of the File Allocation Table
* during allocation of clusters. The lock does not have to be held durring
* deallocation of clusters.
*/
static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
static futex_t fat_alloc_lock = FUTEX_INITIALIZER;
 
/** Walk the cluster chain.
*
326,7 → 325,7
/*
* Search FAT1 for unused clusters.
*/
fibril_mutex_lock(&fat_alloc_lock);
futex_down(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; b++) {
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
350,7 → 349,7
*mcl = lifo[found - 1];
*lcl = lifo[0];
free(lifo);
fibril_mutex_unlock(&fat_alloc_lock);
futex_up(&fat_alloc_lock);
return EOK;
}
}
357,7 → 356,7
}
block_put(blk);
}
fibril_mutex_unlock(&fat_alloc_lock);
futex_up(&fat_alloc_lock);
 
/*
* We could not find enough clusters. Now we need to free the clusters
/branches/dynload/uspace/srv/vfs/vfs_ops.c
43,8 → 43,9
#include <stdlib.h>
#include <string.h>
#include <bool.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/list.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
54,12 → 55,26
/* Forward declarations of static functions. */
static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
 
/** Pending mount structure. */
typedef struct {
link_t link;
char *fs_name; /**< File system name */
char *mp; /**< Mount point */
char *opts; /**< Mount options. */
ipc_callid_t callid; /**< Call ID waiting for the mount */
ipc_callid_t rid; /**< Request ID */
dev_handle_t dev_handle; /**< Device handle */
} pending_req_t;
 
LIST_INITIALIZE(pending_req);
 
/**
* This rwlock prevents the race between a triplet-to-VFS-node resolution and a
* concurrent VFS operation which modifies the file system namespace.
*/
FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
RWLOCK_INITIALIZE(namespace_rwlock);
 
futex_t rootfs_futex = FUTEX_INITIALIZER;
vfs_pair_t rootfs = {
.fs_handle = 0,
.dev_handle = 0
69,24 → 84,21
fs_handle_t fs_handle, char *mp, char *opts)
{
vfs_lookup_res_t mp_res;
vfs_lookup_res_t mr_res;
vfs_node_t *mp_node = NULL;
vfs_node_t *mr_node;
fs_index_t rindex;
size_t rsize;
unsigned rlnkcnt;
ipcarg_t rc;
int phone;
aid_t msg;
ipc_call_t answer;
 
/* Resolve the path to the mountpoint. */
fibril_rwlock_write_lock(&namespace_rwlock);
futex_down(&rootfs_futex);
if (rootfs.fs_handle) {
/* We already have the root FS. */
rwlock_write_lock(&namespace_rwlock);
if (str_cmp(mp, "/") == 0) {
/* Trying to mount root FS over root FS */
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, EBUSY);
return;
}
94,7 → 106,8
rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
if (rc != EOK) {
/* The lookup failed for some reason. */
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
101,7 → 114,8
mp_node = vfs_node_get(&mp_res);
if (!mp_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, ENOMEM);
return;
}
108,12 → 122,19
/*
* Now we hold a reference to mp_node.
* It will be dropped upon the corresponding VFS_IN_UNMOUNT.
* It will be dropped upon the corresponding VFS_UNMOUNT.
* This prevents the mount point from being deleted.
*/
rwlock_write_unlock(&namespace_rwlock);
} else {
/* We still don't have the root file system mounted. */
if (str_cmp(mp, "/") == 0) {
vfs_lookup_res_t mr_res;
vfs_node_t *mr_node;
fs_index_t rindex;
size_t rsize;
unsigned rlnkcnt;
/*
* For this simple, but important case,
* we are almost done.
121,7 → 142,7
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
msg = async_send_1(phone, VFS_OUT_MOUNTED,
msg = async_send_1(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle, &answer);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts,
129,7 → 150,7
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(phone);
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
137,7 → 158,7
vfs_release_phone(phone);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
155,12 → 176,12
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
futex_up(&rootfs_futex);
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
} else {
168,11 → 189,12
* We can't resolve this without the root filesystem
* being mounted first.
*/
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
ipc_answer_0(rid, ENOENT);
return;
}
}
futex_up(&rootfs_futex);
/*
* At this point, we have all necessary pieces: file system and device
179,32 → 201,12
* handles, and we know the mount point VFS node.
*/
int mountee_phone = vfs_grab_phone(fs_handle);
assert(mountee_phone >= 0);
 
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
msg = async_send_4(phone, VFS_OUT_MOUNT,
msg = async_send_4(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
(ipcarg_t) mp_res.triplet.index,
(ipcarg_t) fs_handle,
(ipcarg_t) dev_handle, &answer);
/* send connection */
rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(mountee_phone);
vfs_release_phone(phone);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
ipc_answer_0(rid, rc);
fibril_rwlock_write_unlock(&namespace_rwlock);
return;
}
 
vfs_release_phone(mountee_phone);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
if (rc != EOK) {
213,7 → 215,6
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
fibril_rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
220,31 → 221,44
async_wait_for(msg, &rc);
vfs_release_phone(phone);
if (rc == EOK) {
rindex = (fs_index_t) IPC_GET_ARG1(answer);
rsize = (size_t) IPC_GET_ARG2(answer);
rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
mr_res.triplet.fs_handle = fs_handle;
mr_res.triplet.dev_handle = dev_handle;
mr_res.triplet.index = rindex;
mr_res.size = rsize;
mr_res.lnkcnt = rlnkcnt;
mr_res.type = VFS_NODE_DIRECTORY;
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
} else {
if (rc != EOK) {
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
}
 
ipc_answer_0(rid, rc);
fibril_rwlock_write_unlock(&namespace_rwlock);
}
 
/** Process pending mount requests */
void vfs_process_pending_mount()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true);
if (!fs_handle)
continue;
/* Acknowledge that we know fs_name. */
ipc_answer_0(pr->callid, EOK);
/* Do the mount */
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp,
pr->opts);
free(pr->fs_name);
free(pr->mp);
free(pr->opts);
list_remove(cur);
free(pr);
goto loop;
}
}
 
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
/*
306,7 → 320,7
}
 
/* Check the offered options size. */
if (size > MAX_MNTOPTS_LEN) {
if (size < 0 || size > MAX_MNTOPTS_LEN) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
398,17 → 412,33
* Check if we know a file system with the same name as is in fs_name.
* This will also give us its file system handle.
*/
fibril_mutex_lock(&fs_head_lock);
fs_handle_t fs_handle;
recheck:
fs_handle = fs_name_to_handle(fs_name, false);
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
if (!fs_handle) {
if (flags & IPC_FLAG_BLOCKING) {
fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
goto recheck;
pending_req_t *pr;
 
/* Blocking mount, add to pending list */
pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(mp);
free(fs_name);
free(opts);
return;
}
pr->fs_name = fs_name;
pr->mp = mp;
pr->opts = opts;
pr->callid = callid;
pr->rid = rid;
pr->dev_handle = dev_handle;
link_initialize(&pr->link);
list_append(&pr->link, &pending_req);
return;
}
fibril_mutex_unlock(&fs_head_lock);
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
free(mp);
416,7 → 446,6
free(opts);
return;
}
fibril_mutex_unlock(&fs_head_lock);
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
434,11 → 463,11
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* The POSIX interface is open(path, oflag, mode).
* We can receive oflags and mode along with the VFS_IN_OPEN call;
* the path will need to arrive in another call.
* We can receive oflags and mode along with the VFS_OPEN call; the path
* will need to arrive in another call.
*
* We also receive one private, non-POSIX set of flags called lflag
* used to pass information to vfs_lookup_internal().
448,32 → 477,28
int mode = IPC_GET_ARG3(*request);
size_t len;
 
/* Ignore mode for now. */
(void) mode;
/*
* Make sure that we are called with exactly one of L_FILE and
* L_DIRECTORY. Make sure that the user does not pass L_OPEN.
* L_DIRECTORY.
*/
if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
((lflag & L_OPEN) != 0)) {
if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
(lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
ipc_answer_0(rid, EINVAL);
return;
}
 
if (oflag & O_CREAT)
lflag |= L_CREATE;
if (oflag & O_EXCL)
lflag |= L_EXCLUSIVE;
 
ipc_callid_t callid;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *path = malloc(len + 1);
if (!path) {
ipc_answer_0(callid, ENOMEM);
480,7 → 505,6
ipc_answer_0(rid, ENOMEM);
return;
}
int rc;
if ((rc = ipc_data_write_finalize(callid, path, len))) {
ipc_answer_0(rid, rc);
495,40 → 519,40
* triplet.
*/
if (lflag & L_CREATE)
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
else
fibril_rwlock_read_lock(&namespace_rwlock);
rwlock_read_lock(&namespace_rwlock);
 
/* The path is now populated and we can call vfs_lookup_internal(). */
vfs_lookup_res_t lr;
rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
if (rc != EOK) {
rc = vfs_lookup_internal(path, lflag, &lr, NULL);
if (rc) {
if (lflag & L_CREATE)
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
else
fibril_rwlock_read_unlock(&namespace_rwlock);
rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(path);
return;
}
 
/* Path is no longer needed. */
free(path);
 
vfs_node_t *node = vfs_node_get(&lr);
if (lflag & L_CREATE)
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
else
fibril_rwlock_read_unlock(&namespace_rwlock);
rwlock_read_unlock(&namespace_rwlock);
 
/* Truncate the file if requested and if necessary. */
if (oflag & O_TRUNC) {
fibril_rwlock_write_lock(&node->contents_rwlock);
rwlock_write_lock(&node->contents_rwlock);
if (node->size) {
rc = vfs_truncate_internal(node->fs_handle,
node->dev_handle, node->index, 0);
if (rc) {
fibril_rwlock_write_unlock(&node->contents_rwlock);
rwlock_write_unlock(&node->contents_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, rc);
return;
535,9 → 559,9
}
node->size = 0;
}
fibril_rwlock_write_unlock(&node->contents_rwlock);
rwlock_write_unlock(&node->contents_rwlock);
}
 
/*
* Get ourselves a file descriptor and the corresponding vfs_file_t
* structure.
550,173 → 574,30
}
vfs_file_t *file = vfs_file_get(fd);
file->node = node;
if (oflag & O_APPEND)
if (oflag & O_APPEND)
file->append = true;
 
/*
* The following increase in reference count is for the fact that the
* file is being opened and that a file structure is pointing to it.
* It is necessary so that the file will not disappear when
* vfs_node_put() is called. The reference will be dropped by the
* respective VFS_IN_CLOSE.
* respective VFS_CLOSE.
*/
vfs_node_addref(node);
vfs_node_put(node);
/* Success! Return the new file descriptor to the client. */
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
{
// FIXME: check for sanity of the supplied fs, dev and index
if (!vfs_files_init()) {
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* The interface is open_node(fs, dev, index, oflag).
*/
vfs_lookup_res_t lr;
lr.triplet.fs_handle = IPC_GET_ARG1(*request);
lr.triplet.dev_handle = IPC_GET_ARG2(*request);
lr.triplet.index = IPC_GET_ARG3(*request);
int oflag = IPC_GET_ARG4(*request);
fibril_rwlock_read_lock(&namespace_rwlock);
int rc = vfs_open_node_internal(&lr);
if (rc != EOK) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
vfs_node_t *node = vfs_node_get(&lr);
fibril_rwlock_read_unlock(&namespace_rwlock);
/* Truncate the file if requested and if necessary. */
if (oflag & O_TRUNC) {
fibril_rwlock_write_lock(&node->contents_rwlock);
if (node->size) {
rc = vfs_truncate_internal(node->fs_handle,
node->dev_handle, node->index, 0);
if (rc) {
fibril_rwlock_write_unlock(&node->contents_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, rc);
return;
}
node->size = 0;
}
fibril_rwlock_write_unlock(&node->contents_rwlock);
}
/*
* Get ourselves a file descriptor and the corresponding vfs_file_t
* structure.
*/
int fd = vfs_fd_alloc();
if (fd < 0) {
vfs_node_put(node);
ipc_answer_0(rid, fd);
return;
}
vfs_file_t *file = vfs_file_get(fd);
file->node = node;
if (oflag & O_APPEND)
file->append = true;
/*
* The following increase in reference count is for the fact that the
* file is being opened and that a file structure is pointing to it.
* It is necessary so that the file will not disappear when
* vfs_node_put() is called. The reference will be dropped by the
* respective VFS_IN_CLOSE.
*/
vfs_node_addref(node);
vfs_node_put(node);
/* Success! Return the new file descriptor to the client. */
ipc_answer_1(rid, EOK, fd);
}
 
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_OUT_SYMC request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->dev_handle,
file->node->index, &answer);
 
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
vfs_release_phone(fs_phone);
fibril_mutex_unlock(&file->lock);
int rc = vfs_fd_free(fd);
ipc_answer_0(rid, rc);
}
 
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
/* Lookup the file structure corresponding to the file descriptor. */
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
/*
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
int fs_phone = vfs_grab_phone(file->node->fs_handle);
/* Make a VFS_OUT_CLOSE request at the destination FS server. */
aid_t msg;
ipc_call_t answer;
msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
file->node->index, &answer);
 
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
 
vfs_release_phone(fs_phone);
fibril_mutex_unlock(&file->lock);
int retval = IPC_GET_ARG1(answer);
if (retval != EOK)
ipc_answer_0(rid, retval);
retval = vfs_fd_free(fd);
ipc_answer_0(rid, retval);
}
 
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
{
 
759,7 → 640,7
* Lock the open file structure so that no other thread can manipulate
* the same open file at a time.
*/
fibril_mutex_lock(&file->lock);
futex_down(&file->lock);
 
/*
* Lock the file's node so that no other client can read/write to it at
766,9 → 647,9
* the same time.
*/
if (read)
fibril_rwlock_read_lock(&file->node->contents_rwlock);
rwlock_read_lock(&file->node->contents_rwlock);
else
fibril_rwlock_write_lock(&file->node->contents_rwlock);
rwlock_write_lock(&file->node->contents_rwlock);
 
if (file->node->type == VFS_NODE_DIRECTORY) {
/*
776,7 → 657,7
* while we are in readdir().
*/
assert(read);
fibril_rwlock_read_lock(&namespace_rwlock);
rwlock_read_lock(&namespace_rwlock);
}
int fs_phone = vfs_grab_phone(file->node->fs_handle);
786,7 → 667,7
ipc_call_t answer;
if (!read && file->append)
file->pos = file->node->size;
msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE,
msg = async_send_3(fs_phone, IPC_GET_METHOD(*request),
file->node->dev_handle, file->node->index, file->pos, &answer);
/*
796,32 → 677,31
* don't have to bother.
*/
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
vfs_release_phone(fs_phone);
/* Wait for reply from the FS server. */
ipcarg_t rc;
async_wait_for(msg, &rc);
vfs_release_phone(fs_phone);
size_t bytes = IPC_GET_ARG1(answer);
 
if (file->node->type == VFS_NODE_DIRECTORY)
fibril_rwlock_read_unlock(&namespace_rwlock);
rwlock_read_unlock(&namespace_rwlock);
/* Unlock the VFS node. */
if (read)
fibril_rwlock_read_unlock(&file->node->contents_rwlock);
rwlock_read_unlock(&file->node->contents_rwlock);
else {
/* Update the cached version of node's size. */
if (rc == EOK)
file->node->size = IPC_GET_ARG2(answer);
fibril_rwlock_write_unlock(&file->node->contents_rwlock);
rwlock_write_unlock(&file->node->contents_rwlock);
}
/* Update the position pointer and unlock the open file. */
if (rc == EOK)
file->pos += bytes;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
/*
* FS server's reply is the final result of the whole operation we
855,40 → 735,40
}
 
off_t newpos;
fibril_mutex_lock(&file->lock);
futex_down(&file->lock);
if (whence == SEEK_SET) {
file->pos = off;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_1(rid, EOK, off);
return;
}
if (whence == SEEK_CUR) {
if (file->pos + off < file->pos) {
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, EOVERFLOW);
return;
}
file->pos += off;
newpos = file->pos;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_1(rid, EOK, newpos);
return;
}
if (whence == SEEK_END) {
fibril_rwlock_read_lock(&file->node->contents_rwlock);
rwlock_read_lock(&file->node->contents_rwlock);
size_t size = file->node->size;
fibril_rwlock_read_unlock(&file->node->contents_rwlock);
rwlock_read_unlock(&file->node->contents_rwlock);
if (size + off < size) {
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, EOVERFLOW);
return;
}
newpos = size + off;
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_1(rid, EOK, newpos);
return;
}
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, EINVAL);
}
 
900,7 → 780,7
int fs_phone;
fs_phone = vfs_grab_phone(fs_handle);
rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)dev_handle,
(ipcarg_t)index, (ipcarg_t)size);
vfs_release_phone(fs_phone);
return (int)rc;
917,119 → 797,19
ipc_answer_0(rid, ENOENT);
return;
}
fibril_mutex_lock(&file->lock);
futex_down(&file->lock);
 
fibril_rwlock_write_lock(&file->node->contents_rwlock);
rwlock_write_lock(&file->node->contents_rwlock);
rc = vfs_truncate_internal(file->node->fs_handle,
file->node->dev_handle, file->node->index, size);
if (rc == EOK)
file->node->size = size;
fibril_rwlock_write_unlock(&file->node->contents_rwlock);
rwlock_write_unlock(&file->node->contents_rwlock);
 
fibril_mutex_unlock(&file->lock);
futex_up(&file->lock);
ipc_answer_0(rid, (ipcarg_t)rc);
}
 
void vfs_fstat(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
size_t size = IPC_GET_ARG2(*request);
ipcarg_t rc;
 
vfs_file_t *file = vfs_file_get(fd);
if (!file) {
ipc_answer_0(rid, ENOENT);
return;
}
 
ipc_callid_t callid;
if (!ipc_data_read_receive(&callid, NULL)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
fibril_mutex_lock(&file->lock);
 
int fs_phone = vfs_grab_phone(file->node->fs_handle);
aid_t msg;
msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev_handle,
file->node->index, true, NULL);
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
async_wait_for(msg, &rc);
vfs_release_phone(fs_phone);
 
fibril_mutex_unlock(&file->lock);
ipc_answer_0(rid, rc);
}
 
void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
{
size_t len;
ipc_callid_t callid;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *path = malloc(len + 1);
if (!path) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
int rc;
if ((rc = ipc_data_write_finalize(callid, path, len))) {
ipc_answer_0(rid, rc);
free(path);
return;
}
path[len] = '\0';
 
if (!ipc_data_read_receive(&callid, NULL)) {
free(path);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
vfs_lookup_res_t lr;
fibril_rwlock_read_lock(&namespace_rwlock);
rc = vfs_lookup_internal(path, L_NONE, &lr, NULL);
free(path);
if (rc != EOK) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(callid, rc);
ipc_answer_0(rid, rc);
return;
}
vfs_node_t *node = vfs_node_get(&lr);
if (!node) {
fibril_rwlock_read_unlock(&namespace_rwlock);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
fibril_rwlock_read_unlock(&namespace_rwlock);
 
int fs_phone = vfs_grab_phone(node->fs_handle);
aid_t msg;
msg = async_send_3(fs_phone, VFS_OUT_STAT, node->dev_handle,
node->index, false, NULL);
ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
ipcarg_t rv;
async_wait_for(msg, &rv);
vfs_release_phone(fs_phone);
 
ipc_answer_0(rid, rv);
 
vfs_node_put(node);
}
 
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request)
{
int mode = IPC_GET_ARG1(*request);
1055,14 → 835,11
return;
}
path[len] = '\0';
 
/* Ignore mode for now. */
(void) mode;
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
rc = vfs_lookup_internal(path, lflag, NULL, NULL);
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
free(path);
ipc_answer_0(rid, rc);
}
1093,13 → 870,13
}
path[len] = '\0';
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
lflag &= L_DIRECTORY; /* sanitize lflag */
vfs_lookup_res_t lr;
rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
free(path);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
return;
}
1107,13 → 884,13
/*
* The name has already been unlinked by vfs_lookup_internal().
* We have to get and put the VFS node to ensure that it is
* VFS_OUT_DESTROY'ed after the last reference to it is dropped.
* VFS_DESTROY'ed after the last reference to it is dropped.
*/
vfs_node_t *node = vfs_node_get(&lr);
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
node->lnkcnt--;
fibril_mutex_unlock(&nodes_mutex);
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&nodes_futex);
rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(node);
ipc_answer_0(rid, EOK);
}
1194,11 → 971,11
vfs_lookup_res_t old_lr;
vfs_lookup_res_t new_lr;
vfs_lookup_res_t new_par_lr;
fibril_rwlock_write_lock(&namespace_rwlock);
rwlock_write_lock(&namespace_rwlock);
/* Lookup the node belonging to the old file name. */
rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1206,7 → 983,7
}
vfs_node_t *old_node = vfs_node_get(&old_lr);
if (!old_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
free(old);
free(new);
1215,13 → 992,13
/* Determine the path to the parent of the node with the new name. */
char *parentc = str_dup(newc);
if (!parentc) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
return;
}
char *lastsl = str_rchr(parentc + 1, '/');
char *lastsl = str_rchr(parentc + 1, L'/');
if (lastsl)
*lastsl = '\0';
else
1230,7 → 1007,7
rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
free(parentc); /* not needed anymore */
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, rc);
free(old);
free(new);
1239,7 → 1016,7
/* Check whether linking to the same file system instance. */
if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
(old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, EXDEV); /* different file systems */
free(old);
free(new);
1255,18 → 1032,18
case EOK:
new_node = vfs_node_get(&new_lr);
if (!new_node) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOMEM);
free(old);
free(new);
return;
}
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
new_node->lnkcnt--;
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
break;
default:
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
ipc_answer_0(rid, ENOTEMPTY);
free(old);
free(new);
1275,7 → 1052,7
/* Create the new link for the new name. */
rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
if (new_node)
vfs_node_put(new_node);
ipc_answer_0(rid, rc);
1283,13 → 1060,13
free(new);
return;
}
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
old_node->lnkcnt++;
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
/* Destroy the link for the old name. */
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
if (rc != EOK) {
fibril_rwlock_write_unlock(&namespace_rwlock);
rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
vfs_node_put(new_node);
1298,10 → 1075,10
free(new);
return;
}
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
old_node->lnkcnt--;
fibril_mutex_unlock(&nodes_mutex);
fibril_rwlock_write_unlock(&namespace_rwlock);
futex_up(&nodes_futex);
rwlock_write_unlock(&namespace_rwlock);
vfs_node_put(old_node);
if (new_node)
vfs_node_put(new_node);
1312,4 → 1089,4
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/vfs/vfs.h
28,25 → 28,70
 
/** @addtogroup fs
* @{
*/
*/
 
#ifndef VFS_VFS_H_
#define VFS_VFS_H_
 
#include <ipc/ipc.h>
#include <adt/list.h>
#include <fibril_sync.h>
#include <libadt/list.h>
#include <futex.h>
#include <rwlock.h>
#include <sys/types.h>
#include <devmap.h>
#include <bool.h>
#include <ipc/vfs.h>
 
// FIXME: according to CONFIG_DEBUG
// #define dprintf(...) printf(__VA_ARGS__)
// #define dprintf(...) printf(__VA_ARGS__)
 
#define dprintf(...)
 
#define VFS_FIRST IPC_FIRST_USER_METHOD
 
/* Basic types. */
typedef int16_t fs_handle_t;
typedef int16_t dev_handle_t;
typedef uint32_t fs_index_t;
 
typedef enum {
VFS_READ = VFS_FIRST,
VFS_WRITE,
VFS_TRUNCATE,
VFS_MOUNT,
VFS_UNMOUNT,
VFS_LAST_CMN, /* keep this the last member of this enum */
} vfs_request_cmn_t;
 
typedef enum {
VFS_LOOKUP = VFS_LAST_CMN,
VFS_MOUNTED,
VFS_DESTROY,
VFS_LAST_CLNT, /* keep this the last member of this enum */
} vfs_request_clnt_t;
 
typedef enum {
VFS_REGISTER = VFS_LAST_CMN,
VFS_OPEN,
VFS_CLOSE,
VFS_SEEK,
VFS_MKDIR,
VFS_UNLINK,
VFS_RENAME,
VFS_LAST_SRV, /* keep this the last member of this enum */
} vfs_request_srv_t;
 
#define FS_NAME_MAXLEN 20
 
/**
* 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;
 
/**
* A structure like this will be allocated for each registered file system.
*/
typedef struct {
53,7 → 98,7
link_t fs_link;
vfs_info_t vfs_info;
fs_handle_t fs_handle;
fibril_mutex_t phone_lock;
futex_t phone_futex; /**< Phone serializing futex. */
ipcarg_t phone;
} fs_info_t;
 
60,8 → 105,8
/**
* VFS_PAIR uniquely represents a file system instance.
*/
#define VFS_PAIR \
fs_handle_t fs_handle; \
#define VFS_PAIR \
fs_handle_t fs_handle; \
dev_handle_t dev_handle;
 
/**
71,8 → 116,8
* @note fs_handle, dev_handle and index are meant to be returned in one
* IPC reply.
*/
#define VFS_TRIPLET \
VFS_PAIR; \
#define VFS_TRIPLET \
VFS_PAIR; \
fs_index_t index;
 
typedef struct {
83,6 → 128,45
VFS_TRIPLET;
} vfs_triplet_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
 
typedef enum vfs_node_type {
VFS_NODE_UNKNOWN,
VFS_NODE_FILE,
121,7 → 205,7
/**
* Holding this rwlock prevents modifications of the node's contents.
*/
fibril_rwlock_t contents_rwlock;
rwlock_t contents_rwlock;
} vfs_node_t;
 
/**
130,7 → 214,7
*/
typedef struct {
/** Serializes access to this open file. */
fibril_mutex_t lock;
futex_t lock;
 
vfs_node_t *node;
144,14 → 228,16
off_t pos;
} vfs_file_t;
 
extern fibril_mutex_t nodes_mutex;
extern futex_t nodes_futex;
 
extern fibril_condvar_t fs_head_cv;
extern fibril_mutex_t fs_head_lock;
extern link_t fs_head; /**< List of registered file systems. */
 
extern vfs_pair_t rootfs; /**< Root file system. */
 
#define MAX_PATH_LEN (64 * 1024)
 
#define PLB_SIZE (2 * MAX_PATH_LEN)
 
/** Each instance of this type describes one path lookup in progress. */
typedef struct {
link_t plb_link; /**< Active PLB entries list link. */
159,7 → 245,7
size_t len; /**< Number of characters in this PLB entry. */
} plb_entry_t;
 
extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */
extern futex_t plb_futex; /**< Futex protecting plb and plb_head. */
extern uint8_t *plb; /**< Path Lookup Buffer */
extern link_t plb_head; /**< List of active PLB entries. */
 
166,7 → 252,7
#define MAX_MNTOPTS_LEN 256
 
/** Holding this rwlock prevents changes in file system namespace. */
extern fibril_rwlock_t namespace_rwlock;
extern rwlock_t namespace_rwlock;
 
extern int vfs_grab_phone(fs_handle_t);
extern void vfs_release_phone(int);
173,9 → 259,8
 
extern fs_handle_t fs_name_to_handle(char *, bool);
 
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
vfs_pair_t *, ...);
extern int vfs_open_node_internal(vfs_lookup_res_t *);
extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *, vfs_pair_t *,
...);
 
extern bool vfs_nodes_init(void);
extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *);
194,19 → 279,15
extern void vfs_node_addref(vfs_node_t *);
extern void vfs_node_delref(vfs_node_t *);
 
extern void vfs_process_pending_mount(void);
extern void vfs_register(ipc_callid_t, ipc_call_t *);
extern void vfs_mount(ipc_callid_t, ipc_call_t *);
extern void vfs_open(ipc_callid_t, ipc_call_t *);
extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
extern void vfs_sync(ipc_callid_t, ipc_call_t *);
extern void vfs_close(ipc_callid_t, ipc_call_t *);
extern void vfs_read(ipc_callid_t, ipc_call_t *);
extern void vfs_write(ipc_callid_t, ipc_call_t *);
extern void vfs_seek(ipc_callid_t, ipc_call_t *);
extern void vfs_truncate(ipc_callid_t, ipc_call_t *);
extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
extern void vfs_stat(ipc_callid_t, ipc_call_t *);
extern void vfs_mkdir(ipc_callid_t, ipc_call_t *);
extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
extern void vfs_rename(ipc_callid_t, ipc_call_t *);
/branches/dynload/uspace/srv/vfs/vfs_file.c
40,8 → 40,6
#include <string.h>
#include <assert.h>
#include <bool.h>
#include <fibril.h>
#include <fibril_sync.h>
#include "vfs.h"
 
/**
57,9 → 55,9
* first VFS_OPEN operation.
*
* This resource being per-connection and, in the first place, per-fibril, we
* don't need to protect it by a mutex.
* don't need to protect it by a futex.
*/
fibril_local vfs_file_t **files = NULL;
__thread vfs_file_t **files = NULL;
 
/** Initialize the table of open files. */
bool vfs_files_init(void)
80,23 → 78,19
*/
int vfs_fd_alloc(void)
{
if (!vfs_files_init())
return ENOMEM;
unsigned int i;
int i;
 
for (i = 0; i < MAX_OPEN_FILES; i++) {
if (!files[i]) {
files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
if (!files[i])
return ENOMEM;
memset(files[i], 0, sizeof(vfs_file_t));
fibril_mutex_initialize(&files[i]->lock);
futex_initialize(&files[i]->lock, 1);
vfs_file_addref(files[i]);
return (int) i;
return i;
}
}
return EMFILE;
}
 
109,15 → 103,10
*/
int vfs_fd_free(int fd)
{
if (!vfs_files_init())
return ENOMEM;
if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
return EBADF;
vfs_file_delref(files[fd]);
files[fd] = NULL;
return EOK;
}
 
161,15 → 150,11
*/
vfs_file_t *vfs_file_get(int fd)
{
if (!vfs_files_init())
return NULL;
if ((fd >= 0) && (fd < MAX_OPEN_FILES))
return files[fd];
return NULL;
}
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/vfs/vfs_register.c
45,16 → 45,15
#include <string.h>
#include <ctype.h>
#include <bool.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <futex.h>
#include <libadt/list.h>
#include <as.h>
#include <assert.h>
#include <atomic.h>
#include "vfs.h"
 
FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
LIST_INITIALIZE(fs_head);
atomic_t fs_head_futex = FUTEX_INITIALIZER;
link_t fs_head;
 
atomic_t fs_handle_next = {
.count = 1
160,7 → 159,7
return;
}
link_initialize(&fs_info->fs_link);
fibril_mutex_initialize(&fs_info->phone_lock);
futex_initialize(&fs_info->phone_futex, 1);
rc = ipc_data_write_finalize(callid, &fs_info->vfs_info, size);
if (rc != EOK) {
181,7 → 180,8
return;
}
fibril_mutex_lock(&fs_head_lock);
futex_down(&fs_head_futex);
fibril_inc_sercount();
 
/*
* Check for duplicit registrations.
191,7 → 191,8
* We already register a fs like this.
*/
dprintf("FS is already registered.\n");
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
free(fs_info);
ipc_answer_0(callid, EEXISTS);
ipc_answer_0(rid, EEXISTS);
213,7 → 214,8
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
free(fs_info);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
231,7 → 233,8
if (!ipc_share_in_receive(&callid, &size)) {
dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
list_remove(&fs_info->fs_link);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
245,7 → 248,8
if (size != PLB_SIZE) {
dprintf("Client suggests wrong size of PFB, size = %d\n", size);
list_remove(&fs_info->fs_link);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
ipc_hangup(fs_info->phone);
free(fs_info);
ipc_answer_0(callid, EINVAL);
269,11 → 273,16
fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
ipc_answer_1(rid, EOK, (ipcarg_t) fs_info->fs_handle);
fibril_condvar_broadcast(&fs_head_cv);
fibril_mutex_unlock(&fs_head_lock);
fibril_dec_sercount();
futex_up(&fs_head_futex);
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
/* Process pending mount requests possibly waiting
* for this filesystem implementation.
*/
vfs_process_pending_mount();
}
 
/** For a given file system handle, implement policy for allocating a phone.
285,49 → 294,76
*/
int vfs_grab_phone(fs_handle_t handle)
{
int phone;
 
/*
* For now, we don't try to be very clever and very fast. We simply
* lookup the phone in the fs_head list and duplicate it. The duplicate
* phone will be returned to the client and the client will use it for
* communication. In the future, we should cache the connections so
* that they do not have to be reestablished over and over again.
* For now, we don't try to be very clever and very fast.
* We simply lookup the phone in the fs_head list. We currently don't
* open any additional phones (even though that itself would be pretty
* straightforward; housekeeping multiple open phones to a FS task would
* be more demanding). Instead, we simply take the respective
* phone_futex and keep it until vfs_release_phone().
*/
fibril_mutex_lock(&fs_head_lock);
futex_down(&fs_head_futex);
link_t *cur;
fs_info_t *fs;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->fs_handle == handle) {
fibril_mutex_unlock(&fs_head_lock);
fibril_mutex_lock(&fs->phone_lock);
phone = ipc_connect_me_to(fs->phone, 0, 0, 0);
fibril_mutex_unlock(&fs->phone_lock);
 
assert(phone > 0);
return phone;
futex_up(&fs_head_futex);
/*
* For now, take the futex unconditionally.
* Oh yeah, serialization rocks.
* It will be up'ed in vfs_release_phone().
*/
futex_down(&fs->phone_futex);
/*
* Avoid deadlock with other fibrils in the same thread
* by disabling fibril preemption.
*/
fibril_inc_sercount();
return fs->phone;
}
}
fibril_mutex_unlock(&fs_head_lock);
futex_up(&fs_head_futex);
return 0;
}
 
/** Tell VFS that the phone is not needed anymore.
/** Tell VFS that the phone is in use for any request.
*
* @param phone Phone to FS task.
*/
void vfs_release_phone(int phone)
{
/* TODO: implement connection caching */
ipc_hangup(phone);
bool found = false;
 
/*
* Undo the fibril_inc_sercount() done in vfs_grab_phone().
*/
fibril_dec_sercount();
futex_down(&fs_head_futex);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
if (fs->phone == phone) {
found = true;
futex_up(&fs_head_futex);
futex_up(&fs->phone_futex);
return;
}
}
futex_up(&fs_head_futex);
 
/*
* Not good to get here.
*/
assert(found == true);
}
 
/** Convert file system name to its handle.
*
* @param name File system name.
* @param lock If true, the function will lock and unlock the
* fs_head_lock.
* @param lock If true, the function will down and up the
* fs_head_futex.
*
* @return File system handle or zero if file system not found.
*/
336,7 → 372,7
int handle = 0;
if (lock)
fibril_mutex_lock(&fs_head_lock);
futex_down(&fs_head_futex);
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
346,7 → 382,7
}
}
if (lock)
fibril_mutex_unlock(&fs_head_lock);
futex_up(&fs_head_futex);
return handle;
}
 
/branches/dynload/uspace/srv/vfs/vfs.c
43,6 → 43,7
#include <bool.h>
#include <string.h>
#include <as.h>
#include <libadt/list.h>
#include <atomic.h>
#include "vfs.h"
 
51,7 → 52,7
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
bool keep_on_going = true;
 
/*
* The connection was opened via the IPC_CONNECT_ME_TO call.
* This call needs to be answered.
79,52 → 80,59
case IPC_M_PHONE_HUNGUP:
keep_on_going = false;
break;
case VFS_IN_REGISTER:
case IPC_M_CONNECT_ME_TO:
/*
* Connect the client file system to another one.
*/
/* FIXME:
* Prevent ordinary clients from connecting to file
* system servers directly. This should be solved by
* applying some security mechanisms.
*/
fs_handle = IPC_GET_ARG1(call);
phone = vfs_grab_phone(fs_handle);
(void) ipc_forward_fast(callid, phone, 0, 0, 0,
IPC_FF_NONE);
vfs_release_phone(phone);
break;
case VFS_REGISTER:
vfs_register(callid, &call);
keep_on_going = false;
/*
* Keep the connection open so that a file system can
* later ask us to connect it to another file system.
* This is necessary to support non-root mounts.
*/
break;
case VFS_IN_MOUNT:
case VFS_MOUNT:
vfs_mount(callid, &call);
break;
case VFS_IN_OPEN:
case VFS_OPEN:
vfs_open(callid, &call);
break;
case VFS_IN_OPEN_NODE:
vfs_open_node(callid, &call);
break;
case VFS_IN_CLOSE:
case VFS_CLOSE:
vfs_close(callid, &call);
break;
case VFS_IN_READ:
case VFS_READ:
vfs_read(callid, &call);
break;
case VFS_IN_WRITE:
case VFS_WRITE:
vfs_write(callid, &call);
break;
case VFS_IN_SEEK:
case VFS_SEEK:
vfs_seek(callid, &call);
break;
case VFS_IN_TRUNCATE:
case VFS_TRUNCATE:
vfs_truncate(callid, &call);
break;
case VFS_IN_FSTAT:
vfs_fstat(callid, &call);
break;
case VFS_IN_STAT:
vfs_stat(callid, &call);
break;
case VFS_IN_MKDIR:
case VFS_MKDIR:
vfs_mkdir(callid, &call);
break;
case VFS_IN_UNLINK:
case VFS_UNLINK:
vfs_unlink(callid, &call);
break;
case VFS_IN_RENAME:
case VFS_RENAME:
vfs_rename(callid, &call);
break;
case VFS_IN_SYNC:
vfs_sync(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
139,6 → 147,11
printf(NAME ": HelenOS VFS server\n");
/*
* Initialize the list of registered file systems.
*/
list_initialize(&fs_head);
/*
* Initialize VFS node hash table.
*/
if (!vfs_nodes_init()) {
149,6 → 162,7
/*
* Allocate and initialize the Path Lookup Buffer.
*/
list_initialize(&plb_head);
plb = as_get_mappable_page(PLB_SIZE);
if (!plb) {
printf(NAME ": Cannot allocate a mappable piece of address space\n");
163,10 → 177,10
memset(plb, 0, PLB_SIZE);
/*
* Set a connection handling function/fibril.
* Set a connectio handling function/fibril.
*/
async_set_client_connection(vfs_connection);
 
/*
* Register at the naming service.
*/
/branches/dynload/uspace/srv/vfs/Makefile
69,7 → 69,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/vfs/vfs_node.c
38,14 → 38,15
#include "vfs.h"
#include <stdlib.h>
#include <string.h>
#include <fibril_sync.h>
#include <adt/hash_table.h>
#include <futex.h>
#include <rwlock.h>
#include <libadt/hash_table.h>
#include <assert.h>
#include <async.h>
#include <errno.h>
 
/** Mutex protecting the VFS node hash table. */
FIBRIL_MUTEX_INITIALIZE(nodes_mutex);
/** Futex protecting the VFS node hash table. */
futex_t nodes_futex = FUTEX_INITIALIZER;
 
#define NODES_BUCKETS_LOG 8
#define NODES_BUCKETS (1 << NODES_BUCKETS_LOG)
88,9 → 89,9
*/
void vfs_node_addref(vfs_node_t *node)
{
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
_vfs_node_addref(node);
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
}
 
/** Decrement reference count of a VFS node.
104,7 → 105,7
bool free_vfs_node = false;
bool free_fs_node = false;
 
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
if (node->refcnt-- == 1) {
/*
* We are dropping the last reference to this node.
120,7 → 121,7
if (!node->lnkcnt)
free_fs_node = true;
}
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
 
if (free_fs_node) {
/*
129,7 → 130,7
*/
int phone = vfs_grab_phone(node->fs_handle);
ipcarg_t rc;
rc = async_req_2_0(phone, VFS_OUT_DESTROY,
rc = async_req_2_0(phone, VFS_DESTROY,
(ipcarg_t)node->dev_handle, (ipcarg_t)node->index);
assert(rc == EOK);
vfs_release_phone(phone);
160,12 → 161,12
link_t *tmp;
vfs_node_t *node;
 
fibril_mutex_lock(&nodes_mutex);
futex_down(&nodes_futex);
tmp = hash_table_find(&nodes, key);
if (!tmp) {
node = (vfs_node_t *) malloc(sizeof(vfs_node_t));
if (!node) {
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
return NULL;
}
memset(node, 0, sizeof(vfs_node_t));
176,10 → 177,10
node->lnkcnt = result->lnkcnt;
node->type = result->type;
link_initialize(&node->nh_link);
fibril_rwlock_initialize(&node->contents_rwlock);
rwlock_initialize(&node->contents_rwlock);
hash_table_insert(&nodes, key, &node->nh_link);
} else {
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
if (node->type == VFS_NODE_UNKNOWN &&
result->type != VFS_NODE_UNKNOWN) {
/* Upgrade the node type. */
192,7 → 193,7
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN);
 
_vfs_node_addref(node);
fibril_mutex_unlock(&nodes_mutex);
futex_up(&nodes_futex);
 
return node;
}
232,4 → 233,4
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/vfs/vfs_lookup.c
28,10 → 28,10
 
/** @addtogroup fs
* @{
*/
*/
 
/**
* @file vfs_lookup.c
* @file vfs_lookup.c
* @brief
*/
 
42,28 → 42,27
#include <string.h>
#include <stdarg.h>
#include <bool.h>
#include <fibril_sync.h>
#include <adt/list.h>
#include <futex.h>
#include <libadt/list.h>
#include <vfs/canonify.h>
 
#define min(a, b) ((a) < (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
 
FIBRIL_MUTEX_INITIALIZE(plb_mutex);
LIST_INITIALIZE(plb_head); /**< PLB entry ring buffer. */
futex_t plb_futex = FUTEX_INITIALIZER;
link_t plb_head; /**< PLB entry ring buffer. */
uint8_t *plb = NULL;
 
/** Perform a path lookup.
*
* @param path Path to be resolved; it must be a NULL-terminated
* string.
* @param lflag Flags to be used during lookup.
* @param result Empty structure where the lookup result will be stored.
* Can be NULL.
* @param altroot If non-empty, will be used instead of rootfs as the root
* of the whole VFS tree.
* @param path Path to be resolved; it must be a NULL-terminated
* string.
* @param lflag Flags to be used during lookup.
* @param result Empty structure where the lookup result will be stored.
* Can be NULL.
* @param altroot If non-empty, will be used instead of rootfs as the root
* of the whole VFS tree.
*
* @return EOK on success or an error code from errno.h.
*
* @return EOK on success or an error code from errno.h.
*/
int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
vfs_pair_t *altroot, ...)
92,7 → 91,7
va_end(ap);
}
fibril_mutex_lock(&plb_mutex);
futex_down(&plb_futex);
 
plb_entry_t entry;
link_initialize(&entry.plb_link);
119,7 → 118,7
/*
* The buffer cannot absorb the path.
*/
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
return ELIMIT;
}
} else {
127,7 → 126,7
/*
* The buffer cannot absorb the path.
*/
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
return ELIMIT;
}
}
146,7 → 145,7
*/
list_append(&entry.plb_link, &plb_head);
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
 
/*
* Copy the path into PLB.
159,16 → 158,16
 
ipc_call_t answer;
int phone = vfs_grab_phone(root->fs_handle);
aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (ipcarg_t) first,
aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first,
(ipcarg_t) (first + len - 1) % PLB_SIZE,
(ipcarg_t) root->dev_handle, (ipcarg_t) lflag, (ipcarg_t) index,
&answer);
vfs_release_phone(phone);
 
ipcarg_t rc;
async_wait_for(req, &rc);
vfs_release_phone(phone);
fibril_mutex_lock(&plb_mutex);
 
futex_down(&plb_futex);
list_remove(&entry.plb_link);
/*
* Erasing the path from PLB will come handy for debugging purposes.
175,9 → 174,9
*/
memset(&plb[first], 0, cnt1);
memset(plb, 0, cnt2);
fibril_mutex_unlock(&plb_mutex);
futex_up(&plb_futex);
 
if ((rc == EOK) && (result)) {
if ((rc == EOK) && result) {
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer);
result->triplet.dev_handle = (dev_handle_t) IPC_GET_ARG2(answer);
result->triplet.index = (fs_index_t) IPC_GET_ARG3(answer);
194,39 → 193,6
return rc;
}
 
/** Perform a node open operation.
*
* @return EOK on success or an error code from errno.h.
*
*/
int vfs_open_node_internal(vfs_lookup_res_t *result)
{
int phone = vfs_grab_phone(result->triplet.fs_handle);
ipc_call_t answer;
aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE,
(ipcarg_t) result->triplet.dev_handle,
(ipcarg_t) result->triplet.index, &answer);
ipcarg_t rc;
async_wait_for(req, &rc);
vfs_release_phone(phone);
if (rc == EOK) {
result->size = (size_t) IPC_GET_ARG1(answer);
result->lnkcnt = (unsigned) IPC_GET_ARG2(answer);
if (IPC_GET_ARG3(answer) & L_FILE)
result->type = VFS_NODE_FILE;
else if (IPC_GET_ARG3(answer) & L_DIRECTORY)
result->type = VFS_NODE_DIRECTORY;
else
result->type = VFS_NODE_UNKNOWN;
}
return rc;
}
 
/**
* @}
*/
/branches/dynload/uspace/srv/kbd/Makefile
35,7 → 35,7
include $(LIBC_PREFIX)/Makefile.toolchain
include $(LIBC_PREFIX)/Makefile.app
 
CFLAGS += -Iinclude
CFLAGS += -Iinclude -I../libadt/include
 
## Sources
#
45,7 → 45,7
generic/kbd.c \
genarch/gsp.c \
genarch/stroke.c \
generic/keybuffer.c
generic/key_buffer.c
 
ARCH_SOURCES =
GENARCH_SOURCES = \
60,7 → 60,6
endif
 
ifeq ($(UARCH), arm32)
ifeq ($(MACHINE), testarm)
GENARCH_SOURCES += \
port/gxemul.c
72,12 → 71,6
ctl/stty.c
endif
endif
ifeq ($(MACHINE), integratorcp)
GENARCH_SOURCES += \
port/pl050.c \
ctl/pl050.c
endif
endif
 
ifeq ($(UARCH), ia32)
GENARCH_SOURCES += \
173,7 → 166,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/kbd/include/keybuffer.h
File deleted
/branches/dynload/uspace/srv/kbd/include/layout.h
27,10 → 27,10
*/
 
/** @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
37,12 → 37,12
#ifndef KBD_LAYOUT_H_
#define KBD_LAYOUT_H_
 
#include <kbd/kbd.h>
#include <sys/types.h>
#include <io/console.h>
 
typedef struct {
void (*reset)(void);
wchar_t (*parse_ev)(console_event_t *);
wchar_t (*parse_ev)(kbd_event_t *);
} layout_op_t;
 
extern layout_op_t us_qwerty_op;
53,4 → 53,5
 
/**
* @}
*/
*/
 
/branches/dynload/uspace/srv/kbd/include/kbd.h
27,10 → 27,10
*/
 
/** @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
37,17 → 37,17
#ifndef KBD_KBD_H_
#define KBD_KBD_H_
 
#include <keybuffer.h>
#include <key_buffer.h>
#include <ipc/ipc.h>
 
#define KBD_EVENT 1024
#define KBD_MS_LEFT 1025
#define KBD_MS_RIGHT 1026
#define KBD_MS_MIDDLE 1027
#define KBD_MS_MOVE 1028
#define KBD_EVENT 1024
#define KBD_MS_LEFT 1025
#define KBD_MS_RIGHT 1026
#define KBD_MS_MIDDLE 1027
#define KBD_MS_MOVE 1028
 
typedef enum {
KBD_YIELD = IPC_FIRST_USER_METHOD,
KBD_YIELD = IPC_FIRST_USER_METHOD,
KBD_RECLAIM
} kbd_request_t;
 
61,4 → 61,5
 
/**
* @}
*/
*/
 
/branches/dynload/uspace/srv/kbd/include/key_buffer.h
0,0 → 1,65
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdgen
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
 
#ifndef __KEY_BUFFER_H__
#define __KEY_BUFFER_H__
 
#include <sys/types.h>
#include <kbd/kbd.h>
 
/** Size of buffer for pressed keys */
#define KEYBUFFER_SIZE 128
 
typedef struct {
kbd_event_t fifo[KEYBUFFER_SIZE];
unsigned long head;
unsigned long tail;
unsigned long items;
} keybuffer_t;
 
extern void keybuffer_free(keybuffer_t *);
extern void keybuffer_init(keybuffer_t *);
extern int keybuffer_available(keybuffer_t *);
extern int keybuffer_empty(keybuffer_t *);
extern void keybuffer_push(keybuffer_t *, const kbd_event_t *);
extern int keybuffer_pop(keybuffer_t *, kbd_event_t *);
 
#endif
 
/**
* @}
*/
 
/branches/dynload/uspace/srv/kbd/include/gsp.h
37,7 → 37,7
#ifndef KBD_GSP_H_
#define KBD_GSP_H_
 
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
 
enum {
GSP_END = -1, /**< Terminates a sequence. */
/branches/dynload/uspace/srv/kbd/port/pl050.c
File deleted
/branches/dynload/uspace/srv/kbd/port/i8042.c
135,8 → 135,8
(void) pio_read_8(&i8042->data);
/* Enable kbd */
i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status;
i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data;
i8042_kbd.cmds[0].addr = &((i8042_t *) i8042_kernel)->status;
i8042_kbd.cmds[3].addr = &((i8042_t *) i8042_kernel)->data;
ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &i8042_kbd);
 
int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE;
/branches/dynload/uspace/srv/kbd/generic/keybuffer.c
File deleted
/branches/dynload/uspace/srv/kbd/generic/kbd.c
28,10 → 28,10
 
/**
* @addtogroup kbdgen generic
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
*/
/** @file
*/
 
45,12 → 45,12
#include <ipc/ns.h>
#include <async.h>
#include <errno.h>
#include <adt/fifo.h>
#include <io/console.h>
#include <io/keycode.h>
#include <libadt/fifo.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
 
#include <kbd.h>
#include <keybuffer.h>
#include <key_buffer.h>
#include <kbd_port.h>
#include <kbd_ctl.h>
#include <layout.h>
88,7 → 88,7
 
void kbd_push_ev(int type, unsigned int key)
{
console_event_t ev;
kbd_event_t ev;
unsigned mod_mask;
 
switch (key) {
102,7 → 102,7
}
 
if (mod_mask != 0) {
if (type == KEY_PRESS)
if (type == KE_PRESS)
mods = mods | mod_mask;
else
mods = mods & ~mod_mask;
116,7 → 116,7
}
 
if (mod_mask != 0) {
if (type == KEY_PRESS) {
if (type == KE_PRESS) {
/*
* Only change lock state on transition from released
* to pressed. This prevents autorepeat from messing
133,7 → 133,7
printf("mods: 0x%x\n", mods);
printf("keycode: %u\n", key);
*/
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
if (type == KE_PRESS && (mods & KM_LCTRL) &&
key == KC_F1) {
active_layout = 0;
layout[active_layout]->reset();
140,7 → 140,7
return;
}
 
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
if (type == KE_PRESS && (mods & KM_LCTRL) &&
key == KC_F2) {
active_layout = 1;
layout[active_layout]->reset();
147,7 → 147,7
return;
}
 
if (type == KEY_PRESS && (mods & KM_LCTRL) &&
if (type == KE_PRESS && (mods & KM_LCTRL) &&
key == KC_F3) {
active_layout = 2;
layout[active_layout]->reset();
/branches/dynload/uspace/srv/kbd/generic/key_buffer.c
0,0 → 1,117
/*
* Copyright (c) 2006 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup kbdgen
* @brief HelenOS generic uspace keyboard handler.
* @ingroup kbd
* @{
*/
/** @file
*/
#include <key_buffer.h>
#include <futex.h>
 
atomic_t keybuffer_futex = FUTEX_INITIALIZER;
 
/** Clear key buffer.
*/
void keybuffer_free(keybuffer_t *keybuffer)
{
futex_down(&keybuffer_futex);
keybuffer->head = 0;
keybuffer->tail = 0;
keybuffer->items = 0;
futex_up(&keybuffer_futex);
}
 
/** Key buffer initialization.
*
*/
void keybuffer_init(keybuffer_t *keybuffer)
{
keybuffer_free(keybuffer);
}
 
/** Get free space in buffer.
* This function is useful for processing some scancodes that are translated
* to more than one character.
* @return empty buffer space
*/
int keybuffer_available(keybuffer_t *keybuffer)
{
return KEYBUFFER_SIZE - keybuffer->items;
}
 
/**
* @return nonzero, if buffer is not empty.
*/
int keybuffer_empty(keybuffer_t *keybuffer)
{
return (keybuffer->items == 0);
}
 
/** Push key event to key buffer.
*
* If the buffer is full, the event is ignored.
*
* @param keybuffer The keybuffer.
* @param ev The event to push.
*/
void keybuffer_push(keybuffer_t *keybuffer, const kbd_event_t *ev)
{
futex_down(&keybuffer_futex);
if (keybuffer->items < KEYBUFFER_SIZE) {
keybuffer->fifo[keybuffer->tail] = *ev;
keybuffer->tail = (keybuffer->tail + 1) % KEYBUFFER_SIZE;
keybuffer->items++;
}
futex_up(&keybuffer_futex);
}
 
/** Pop event from buffer.
*
* @param edst Pointer to where the event should be saved.
* @return Zero on empty buffer, nonzero otherwise.
*/
int keybuffer_pop(keybuffer_t *keybuffer, kbd_event_t *edst)
{
futex_down(&keybuffer_futex);
if (keybuffer->items > 0) {
keybuffer->items--;
*edst = (keybuffer->fifo[keybuffer->head]) ;
keybuffer->head = (keybuffer->head + 1) % KEYBUFFER_SIZE;
futex_up(&keybuffer_futex);
return 1;
}
futex_up(&keybuffer_futex);
return 0;
}
 
/**
* @}
*/
/branches/dynload/uspace/srv/kbd/layout/us_qwerty.c
27,17 → 27,17
*/
 
/** @addtogroup kbd
* @brief US QWERTY layout.
* @brief US QWERTY leyout.
* @{
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(console_event_t *ev);
static wchar_t layout_parse_ev(kbd_event_t *ev);
 
layout_op_t us_qwerty_op = {
layout_reset,
203,7 → 203,7
{
}
 
static wchar_t layout_parse_ev(console_event_t *ev)
static wchar_t layout_parse_ev(kbd_event_t *ev)
{
wchar_t c;
 
/branches/dynload/uspace/srv/kbd/layout/cz.c
27,23 → 27,23
*/
 
/** @addtogroup kbd
* @brief Czech QWERTZ layout.
* @brief US QWERTY leyout.
* @{
*/
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <bool.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(console_event_t *ev);
static wchar_t layout_parse_ev(kbd_event_t *ev);
 
enum m_state {
ms_start,
ms_hacek,
ms_carka
ms_carka
};
 
static enum m_state mstate;
272,7 → 272,7
return map[key];
}
 
static wchar_t parse_ms_hacek(console_event_t *ev)
static wchar_t parse_ms_hacek(kbd_event_t *ev)
{
wchar_t c;
 
290,7 → 290,7
return c;
}
 
static wchar_t parse_ms_carka(console_event_t *ev)
static wchar_t parse_ms_carka(kbd_event_t *ev)
{
wchar_t c;
 
308,7 → 308,7
return c;
}
 
static wchar_t parse_ms_start(console_event_t *ev)
static wchar_t parse_ms_start(kbd_event_t *ev)
{
wchar_t c;
 
383,26 → 383,21
mstate = ms_start;
}
 
static wchar_t layout_parse_ev(console_event_t *ev)
static wchar_t layout_parse_ev(kbd_event_t *ev)
{
if (ev->type != KEY_PRESS)
return 0;
if (ev->type != KE_PRESS)
return '\0';
 
if (key_is_mod(ev->key))
return 0;
return '\0';
 
switch (mstate) {
case ms_start:
return parse_ms_start(ev);
case ms_hacek:
return parse_ms_hacek(ev);
case ms_carka:
return parse_ms_carka(ev);
case ms_start: return parse_ms_start(ev);
case ms_hacek: return parse_ms_hacek(ev);
case ms_carka: return parse_ms_carka(ev);
}
return 0;
}
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/kbd/layout/us_dvorak.c
32,12 → 32,12
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <layout.h>
 
static void layout_reset(void);
static wchar_t layout_parse_ev(console_event_t *ev);
static wchar_t layout_parse_ev(kbd_event_t *ev);
 
layout_op_t us_dvorak_op = {
layout_reset,
209,7 → 209,7
{
}
 
static wchar_t layout_parse_ev(console_event_t *ev)
static wchar_t layout_parse_ev(kbd_event_t *ev)
{
wchar_t c;
 
/branches/dynload/uspace/srv/kbd/ctl/pl050.c
File deleted
/branches/dynload/uspace/srv/kbd/ctl/pc.c
32,12 → 32,12
*/
/**
* @file
* @brief PC keyboard controller driver.
* @brief PC keyboard controller driver.
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
 
188,7 → 188,7
 
void kbd_ctl_parse_scancode(int scancode)
{
console_ev_type_t type;
kbd_ev_type_t type;
unsigned int key;
int *map;
size_t map_length;
207,9 → 207,6
map = scanmap_e0;
map_length = sizeof(scanmap_e0) / sizeof(int);
break;
default:
map = NULL;
map_length = 0;
}
 
ds = ds_s;
216,12 → 213,12
 
if (scancode & 0x80) {
scancode &= ~0x80;
type = KEY_RELEASE;
type = KE_RELEASE;
} else {
type = KEY_PRESS;
type = KE_PRESS;
}
 
if ((scancode < 0) || ((size_t) scancode >= map_length))
if (scancode < 0 || scancode >= map_length)
return;
 
key = map[scancode];
/branches/dynload/uspace/srv/kbd/ctl/stty.c
36,7 → 36,8
*/
 
#include <kbd.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
#include <stroke.h>
/branches/dynload/uspace/srv/kbd/ctl/sun.c
36,8 → 36,8
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
 
#define KBD_KEY_RELEASE 0x80
52,7 → 52,7
 
void kbd_ctl_parse_scancode(int scancode)
{
console_ev_type_t type;
kbd_ev_type_t type;
unsigned int key;
 
if (scancode < 0 || scancode >= 0x100)
63,9 → 63,9
 
if (scancode & KBD_KEY_RELEASE) {
scancode &= ~KBD_KEY_RELEASE;
type = KEY_RELEASE;
type = KE_RELEASE;
} else {
type = KEY_PRESS;
type = KE_PRESS;
}
 
key = scanmap_simple[scancode];
/branches/dynload/uspace/srv/kbd/ctl/gxe_fb.c
36,8 → 36,8
*/
 
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
#include <kbd_ctl.h>
#include <gsp.h>
#include <stroke.h>
/branches/dynload/uspace/srv/kbd/genarch/stroke.c
31,18 → 31,17
*/
/**
* @file
* @brief Stroke simulator.
* @brief Stroke simulator.
*
* When simulating a keyboard using a serial TTY we need to convert the
* recognized strokes (such as Shift-A) to sequences of key presses and
* releases (such as 'press Shift, press A, release A, release Shift').
*
*/
 
#include <stroke.h>
#include <kbd.h>
#include <io/console.h>
#include <io/keycode.h>
#include <kbd/kbd.h>
#include <kbd/keycode.h>
 
/** Correspondence between modifers and the modifier keycodes. */
static unsigned int mods_keys[][2] = {
59,7 → 58,7
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KEY_PRESS, mods_keys[i][1]);
kbd_push_ev(KE_PRESS, mods_keys[i][1]);
}
++i;
}
66,8 → 65,8
 
/* Simulate key press and release. */
if (key != 0) {
kbd_push_ev(KEY_PRESS, key);
kbd_push_ev(KEY_RELEASE, key);
kbd_push_ev(KE_PRESS, key);
kbd_push_ev(KE_RELEASE, key);
}
 
/* Simulate modifier releases. */
74,7 → 73,7
i = 0;
while (mods_keys[i][0] != 0) {
if (mod & mods_keys[i][0]) {
kbd_push_ev(KEY_RELEASE, mods_keys[i][1]);
kbd_push_ev(KE_RELEASE, mods_keys[i][1]);
}
++i;
}
82,4 → 81,4
 
/**
* @}
*/
*/
/branches/dynload/uspace/srv/kbd/genarch/gsp.c
49,7 → 49,7
*/
 
#include <gsp.h>
#include <adt/hash_table.h>
#include <libadt/hash_table.h>
#include <stdlib.h>
#include <stdio.h>
 
244,7 → 244,7
key[0] = t->old_state;
key[1] = t->input;
 
hash_table_insert(&p->trans, key, &t->link);
hash_table_insert(&p->trans, &key, &t->link);
}
 
/** Allocate transition structure. */
276,8 → 276,7
gsp_trans_t *t;
 
t = hash_table_get_instance(item, gsp_trans_t, link);
return ((key[0] == (unsigned long) t->old_state)
&& (key[1] == (unsigned long) t->input));
return (key[0] == t->old_state && key[1] == t->input);
}
 
static void trans_op_remove_callback(link_t *item)
/branches/dynload/uspace/srv/pci/libpci/names.c
150,7 → 150,7
int cat = -1;
int nest;
static const char parse_error[] = "Parse error";
size_t i;
int i;
 
*lino = 0;
for (i = 0; i < sizeof(pci_ids) / sizeof(char *); i++) {
330,7 → 330,7
iv = va_arg(args, int);
if (num)
res = snprintf(buf, size, "%04x", iv);
else if ((v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0)) != 0)
else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0))
return (char *) v->name;
else
res = snprintf(buf, size, "Unknown vendor %04x", iv);
340,7 → 340,7
id = va_arg(args, int);
if (num)
res = snprintf(buf, size, "%04x", id);
else if ((d = id_lookup(a, ID_DEVICE, iv, id, 0, 0)) != 0)
else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0))
return (char *) d->name;
else if (synth)
res = snprintf(buf, size, "Unknown device %04x", id);
370,7 → 370,7
isv = va_arg(args, int);
if (num)
res = snprintf(buf, size, "%04x", isv);
else if ((v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) != 0)
else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0))
return (char *) v->name;
else if (synth)
res = snprintf(buf, size, "Unknown vendor %04x", isv);
384,7 → 384,7
isd = va_arg(args, int);
if (num)
res = snprintf(buf, size, "%04x", isd);
else if ((d = id_lookup_subsys(a, iv, id, isv, isd)) != 0)
else if (d = id_lookup_subsys(a, iv, id, isv, isd))
return (char *) d->name;
else if (synth)
res = snprintf(buf, size, "Unknown device %04x", isd);
415,9 → 415,9
icls = va_arg(args, int);
if (num)
res = snprintf(buf, size, "%04x", icls);
else if ((cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0)) != 0)
else if (cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0))
return (char *) cls->name;
else if ((cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) != 0)
else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0))
res = snprintf(buf, size, "%s [%04x]", cls->name, icls);
else if (synth)
res = snprintf(buf, size, "Class %04x", icls);
429,7 → 429,7
ipif = va_arg(args, int);
if (num)
res = snprintf(buf, size, "%02x", ipif);
else if ((pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0)) != 0)
else if (pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0))
return (char *) pif->name;
else if (icls == 0x0101 && !(ipif & 0x70)) {
/* IDE controllers have complex prog-if semantics */
/branches/dynload/uspace/srv/pci/libpci/i386-ports.c
79,14 → 79,14
d.func = 0;
for (d.dev = 0; d.dev < 32; d.dev++) {
u16 class, vendor;
if ((m->read(&d, PCI_CLASS_DEVICE, (byte *) & class,
if (m->read(&d, PCI_CLASS_DEVICE, (byte *) & class,
sizeof(class))
&& (class == cpu_to_le16(PCI_CLASS_BRIDGE_HOST)
|| class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA)))
|| (m->read(&d, PCI_VENDOR_ID, (byte *) & vendor,
|| class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA))
|| m->read(&d, PCI_VENDOR_ID, (byte *) & vendor,
sizeof(vendor))
&& (vendor == cpu_to_le16(PCI_VENDOR_ID_INTEL)
|| vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ)))) {
|| vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ))) {
a->debug("...outside the Asylum at 0/%02x/0",
d.dev);
return 1;
/branches/dynload/uspace/srv/pci/libpci/generic.c
29,7 → 29,7
for (dev = 0; dev < 32; dev++) {
t->dev = dev;
multi = 0;
for (t->func = 0; !t->func || (multi && t->func < 8);
for (t->func = 0; !t->func || multi && t->func < 8;
t->func++) {
u32 vd = pci_read_long(t, PCI_VENDOR_ID);
struct pci_dev *d;
/branches/dynload/uspace/srv/pci/libpci/pci_ids.h
386,7 → 386,7
" 1043 c01b A9600XT/TD (Secondary)",
" 174b 7c28 Sapphire Radeon 9600XT (Secondary)",
" 1787 4003 Radeon 9600 XT (Secondary)",
" 4173 RV350 \?\? [Radeon 9550] (Secondary)",
" 4173 RV350 ?? [Radeon 9550] (Secondary)",
" 4237 Radeon 7000 IGP",
" 4242 R200 BB [Radeon All in Wonder 8500DV]",
" 1002 02aa Radeon 8500 AIW DV Edition",
668,7 → 668,7
" 1002 002a Rage 128 Pro AIW AGP",
" 1002 0048 Rage Fury Pro",
" 1002 2000 Rage Fury MAXX AGP 4x (TMDS) (VGA device)",
" 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device\?!)",
" 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)",
" 5047 Rage 128 PG/PRO",
" 5048 Rage 128 PH/PRO AGP 2x",
" 5049 Rage 128 PI/PRO AGP 4x",
1635,7 → 1635,7
" 1028 0106 PowerEdge 4600",
" 1028 0121 PowerEdge 2650",
"102b Matrox Graphics, Inc.",
" 0010 MGA-I [Impression\?]",
" 0010 MGA-I [Impression?]",
" 0100 MGA 1064SG [Mystique]",
" 0518 MGA-II [Athena]",
" 0519 MGA 2064W [Millennium]",
2437,7 → 2437,7
" 9922 W99200F/W9922PF MPEG-1/2 Video Encoder",
" 9970 W9970CF",
"1051 Anigma, Inc.",
"1052 \?Young Micro Systems",
"1052 ?Young Micro Systems",
"1053 Young Micro Systems",
"1054 Hitachi, Ltd",
"1055 Efar Microsystems",
3048,7 → 3048,7
" 0369 Bt878 Video Capture",
" 1002 0001 TV-Wonder",
" 1002 0003 TV-Wonder/VE",
" 036c Bt879(\?\?) Video Capture",
" 036c Bt879(??) Video Capture",
" 13e9 0070 Win/TV (Video Section)",
" 036e Bt878 Video Capture",
" 0070 13eb WinTV Series",
4123,7 → 4123,7
" 01de Quadro FX 350",
" 10de 01dc Quadro FX Go350M",
" 01df GeForce 7300 GS",
" 01e0 nForce2 AGP (different version\?)",
" 01e0 nForce2 AGP (different version?)",
" 147b 1c09 NV7 Motherboard",
" 01e8 nForce2 AGP",
" 01ea nForce2 Memory Controller 0",
5096,7 → 5096,7
" 1113 1211 EN-1207D Fast Ethernet Adapter",
" 1216 EN-1216 Ethernet Adapter",
" 1113 2242 EN2242 10/100 Ethernet Mini-PCI Card",
" 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX \?]",
" 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?]",
" 1217 EN-1217 Ethernet Adapter",
" 5105 10Mbps Network card",
" 9211 EN-1207D Fast Ethernet Adapter",
6556,7 → 6556,7
"123e Simutech, Inc.",
"123f C-Cube Microsystems",
" 00e4 MPEG",
" 8120 E4\?",
" 8120 E4?",
" 11bd 0006 DV500 E4",
" 11bd 000a DV500 E4",
" 11bd 000f DV500 E4",
6632,7 → 6632,7
" 0640 Aries 16000P",
"125d ESS Technology",
" 0000 ES336H Fax Modem (Early Model)",
" 1948 Solo\?",
" 1948 Solo?",
" 1968 ES1968 Maestro 2",
" 1028 0085 ES1968 Maestro-2 PCI",
" 1033 8051 ES1968 Maestro-2 Audiodrive",
6922,7 → 6922,7
" 122d 4056 MSP3880SP-U",
" 122d 4057 MSP3880SP-A",
" 4311 Riptide HSF 56k PCI Modem",
" 127a 4311 Ring Modular\? Riptide HSF RT HP Dom",
" 127a 4311 Ring Modular? Riptide HSF RT HP Dom",
" 13e0 0210 HP-GVC",
" 4320 Riptide PCI Audio Controller",
" 1235 4320 Riptide PCI Audio Controller",
8382,7 → 8382,7
" 4325 BCM43xG 802.11b/g",
" 1414 0003 Wireless Notebook Adapter MN-720",
" 1414 0004 Wireless PCI Adapter MN-730",
" 4326 BCM4307 Chipcommon I/O Controller\?",
" 4326 BCM4307 Chipcommon I/O Controller?",
" 4401 BCM4401 100Base-T",
" 1043 80a8 A7V8X motherboard",
" 4402 BCM4402 Integrated 10/100BaseT",
8691,7 → 8691,7
"1504 KAISER Electronics",
"1505 ITA INGENIEURBURO FUR TESTAUFGABEN GmbH",
"1506 CHAMELEON Systems Inc",
"1507 Motorola \?\? / HTEC",
"1507 Motorola ?? / HTEC",
" 0001 MPC105 [Eagle]",
" 0002 MPC106 [Grackle]",
" 0003 MPC8240 [Kahlua]",
9467,7 → 9467,7
"270b Xantel Corporation",
"270f Chaintech Computer Co. Ltd",
"2711 AVID Technology Inc.",
"2a15 3D Vision(\?\?\?)",
"2a15 3D Vision(???)",
"3000 Hansol Electronics Inc.",
"3142 Post Impression Systems.",
"3388 Hint Corp",
/branches/dynload/uspace/srv/pci/update-ids
1,6 → 1,6
#! /bin/bash
 
wget -O pci.ids http://pciids.sourceforge.net/v2.2/pci.ids
wget http://pciids.sourceforge.net/v2.2/pci.ids
 
cat > pci_ids.h <<EOF
/* DO NOT EDIT, THIS FILE IS AUTOMATICALLY GENERATED */
7,8 → 7,7
char *pci_ids[] = {
EOF
 
cat pci.ids | grep -v '^#.*' | grep -v '^$' | tr \" \' | \
sed -n 's/\(.*\)/"\1",/p' | sed 's/?/\\?/g' >> pci_ids.h
cat pci.ids | grep -v '^#.*' | grep -v '^$' | tr \" \' | sed -n 's/\(.*\)/"\1",/p' >> pci_ids.h
 
cat >> pci_ids.h <<EOF
""
/branches/dynload/uspace/srv/ns/clonable.c
File deleted
/branches/dynload/uspace/srv/ns/task.h
File deleted
/branches/dynload/uspace/srv/ns/ns.h
File deleted
/branches/dynload/uspace/srv/ns/clonable.h
File deleted
/branches/dynload/uspace/srv/ns/service.c
File deleted
/branches/dynload/uspace/srv/ns/task.c
File deleted
/branches/dynload/uspace/srv/ns/service.h
File deleted
/branches/dynload/uspace/srv/ns/ns.c
35,28 → 35,93
* @brief Naming service for HelenOS IPC.
*/
 
 
#include <ipc/ipc.h>
#include <ipc/ns.h>
#include <ipc/services.h>
#include <ipc/ns.h>
#include <stdio.h>
#include <bool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
#include <sysinfo.h>
#include <loader/loader.h>
#include <ddi.h>
#include <as.h>
#include <ddi.h>
#include <event.h>
#include <macros.h>
#include <sysinfo.h>
#include "ns.h"
#include "service.h"
#include "clonable.h"
#include "task.h"
 
#define NAME "ns"
 
#define NS_HASH_TABLE_CHAINS 20
 
static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
static void connect_to_service(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid);
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid);
 
 
/* Static functions implementing NS hash table operations. */
static hash_index_t ns_hash(unsigned long *key);
static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
static void ns_remove(link_t *item);
 
/** Operations for NS hash table. */
static hash_table_operations_t ns_hash_table_ops = {
.hash = ns_hash,
.compare = ns_compare,
.remove_callback = ns_remove
};
 
/** NS hash table structure. */
static hash_table_t ns_hash_table;
 
/** NS hash table item. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipcarg_t phone; /**< Phone registered with the service. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
} hashed_service_t;
 
/** Pending connection structure. */
typedef struct {
link_t link;
ipcarg_t service; /**< Number of the service. */
ipc_callid_t callid; /**< Call ID waiting for the connection */
ipcarg_t arg2; /**< Second argument */
ipcarg_t arg3; /**< Third argument */
} pending_req_t;
 
static link_t pending_req;
 
/** Request for connection to a clonable service. */
typedef struct {
link_t link;
ipcarg_t service;
ipc_call_t call;
ipc_callid_t callid;
} cs_req_t;
 
/** List of clonable-service connection requests. */
static link_t cs_req;
 
static void *clockaddr = NULL;
static void *klogaddr = NULL;
 
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr,
size_t pages, void **addr)
/** Return true if @a service is clonable. */
static bool service_clonable(int service)
{
return (service == SERVICE_LOAD);
}
 
static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr, count_t pages, void **addr)
{
if (ph_addr == NULL) {
ipc_answer_0(callid, ENOENT);
return;
80,32 → 145,57
ipc_answer_2(callid, EOK, (ipcarg_t) *addr, AS_AREA_READ);
}
 
/** Process pending connection requests */
static void process_pending_req()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
unsigned long keys[3] = {
pr->service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link)
continue;
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,
pr->arg2, pr->arg3, 0, IPC_FF_NONE);
if (!(pr->callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(pr->callid, retval);
list_remove(cur);
free(pr);
goto loop;
}
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS IPC Naming Service\n");
int rc = service_init();
if (rc != EOK)
return rc;
if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3,
&ns_hash_table_ops)) {
printf(NAME ": No memory available for services\n");
return ENOMEM;
}
rc = clonable_init();
if (rc != EOK)
return rc;
list_initialize(&pending_req);
list_initialize(&cs_req);
rc = task_init();
if (rc != EOK)
return rc;
printf(NAME ": Accepting connections\n");
while (true) {
process_pending_conn();
process_pending_wait();
process_pending_req();
ipc_call_t call;
ipc_callid_t callid = ipc_wait_for_call(&call);
task_id_t id;
ipcarg_t retval;
switch (IPC_GET_METHOD(call)) {
112,14 → 202,10
case IPC_M_SHARE_IN:
switch (IPC_GET_ARG3(call)) {
case SERVICE_MEM_REALTIME:
get_as_area(callid, &call,
(void *) sysinfo_value("clock.faddr"),
1, &clockaddr);
get_as_area(callid, &call, sysinfo_value("clock.faddr"), 1, &clockaddr);
break;
case SERVICE_MEM_KLOG:
get_as_area(callid, &call,
(void *) sysinfo_value("klog.faddr"),
sysinfo_value("klog.pages"), &klogaddr);
get_as_area(callid, &call, sysinfo_value("klog.faddr"), sysinfo_value("klog.pages"), &klogaddr);
break;
default:
ipc_answer_0(callid, ENOENT);
126,7 → 212,7
}
continue;
case IPC_M_PHONE_HUNGUP:
retval = ns_task_disconnect(&call);
retval = EOK;
break;
case IPC_M_CONNECT_TO_ME:
/*
155,20 → 241,6
continue;
}
break;
case NS_PING:
retval = EOK;
break;
case NS_TASK_WAIT:
id = (task_id_t)
MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
wait_for_task(id, &call, callid);
continue;
case NS_ID_INTRO:
retval = ns_task_id_intro(&call);
break;
case NS_RETVAL:
retval = ns_task_retval(&call);
break;
default:
retval = ENOENT;
break;
182,6 → 254,213
return 0;
}
 
/** Register service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
{
unsigned long keys[3] = {
service,
call->in_phone_hash,
0
};
if (hash_table_find(&ns_hash_table, keys))
return EEXISTS;
hashed_service_t *hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
if (!hs)
return ENOMEM;
link_initialize(&hs->link);
hs->service = service;
hs->phone = phone;
hs->in_phone_hash = call->in_phone_hash;
hash_table_insert(&ns_hash_table, keys, &hs->link);
return 0;
}
 
/** Connect client to service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
{
ipcarg_t retval;
unsigned long keys[3] = {
service,
0,
0
};
link_t *link = hash_table_find(&ns_hash_table, keys);
if (!link) {
if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {
/* Blocking connection, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
retval = ENOMEM;
goto out;
}
pr->service = service;
pr->callid = callid;
pr->arg2 = IPC_GET_ARG2(*call);
pr->arg3 = IPC_GET_ARG3(*call);
list_append(&pr->link, &pending_req);
return;
}
retval = ENOENT;
goto out;
}
hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
out:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, retval);
}
 
/** Register clonable service.
*
* @param service Service to be registered.
* @param phone Phone to be used for connections to the service.
* @param call Pointer to call structure.
*
*/
void register_clonable(ipcarg_t service, ipcarg_t phone, ipc_call_t *call,
ipc_callid_t callid)
{
if (list_empty(&cs_req)) {
/* There was no pending connection request. */
printf(NAME ": Unexpected clonable server.\n");
ipc_answer_0(callid, EBUSY);
return;
}
cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
list_remove(&csr->link);
/* Currently we can only handle a single type of clonable service. */
assert(csr->service == SERVICE_LOAD);
ipc_answer_0(callid, EOK);
int rc = ipc_forward_fast(csr->callid, phone, IPC_GET_ARG2(csr->call),
IPC_GET_ARG3(csr->call), 0, IPC_FF_NONE);
 
free(csr);
ipc_hangup(phone);
}
 
/** Connect client to clonable service.
*
* @param service Service to be connected to.
* @param call Pointer to call structure.
* @param callid Call ID of the request.
*
* @return Zero on success or a value from @ref errno.h.
*
*/
void connect_to_clonable(ipcarg_t service, ipc_call_t *call,
ipc_callid_t callid)
{
assert(service == SERVICE_LOAD);
cs_req_t *csr = malloc(sizeof(cs_req_t));
if (csr == NULL) {
ipc_answer_0(callid, ENOMEM);
return;
}
/* Spawn a loader. */
int rc = loader_spawn("loader");
if (rc < 0) {
free(csr);
ipc_answer_0(callid, rc);
return;
}
csr->service = service;
csr->call = *call;
csr->callid = callid;
/*
* We can forward the call only after the server we spawned connects
* to us. Meanwhile we might need to service more connection requests.
* Thus we store the call in a queue.
*/
list_append(&csr->link, &cs_req);
}
 
/** Compute hash index into NS hash table.
*
* @param key Pointer keys. However, only the first key (i.e. service number)
* is used to compute the hash index.
*
* @return Hash index corresponding to key[0].
*
*/
hash_index_t ns_hash(unsigned long *key)
{
assert(key);
return (*key % NS_HASH_TABLE_CHAINS);
}
 
/** Compare a key with hashed item.
*
* This compare function always ignores the third key.
* It exists only to make it possible to remove records
* originating from connection with key[1] in_phone_hash
* value. Note that this is close to being classified
* as a nasty hack.
*
* @param key Array of keys.
* @param keys Must be lesser or equal to 3.
* @param item Pointer to a hash table item.
*
* @return Non-zero if the key matches the item, zero otherwise.
*
*/
int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
assert(key);
assert(keys <= 3);
assert(item);
hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
if (keys == 2)
return key[1] == hs->in_phone_hash;
else
return key[0] == hs->service;
}
 
/** Perform actions after removal of item from the hash table.
*
* @param item Item that was removed from the hash table.
*
*/
void ns_remove(link_t *item)
{
assert(item);
free(hash_table_get_instance(item, hashed_service_t, link));
}
 
/**
* @}
*/
/branches/dynload/uspace/srv/ns/Makefile
41,10 → 41,7
 
OUTPUT = ns
SOURCES = \
ns.c \
service.c \
clonable.c \
task.c
ns.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
66,7 → 63,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/loader/main.c
52,12 → 52,10
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/loader.h>
#include <ipc/ns.h>
#include <macros.h>
#include <loader/pcb.h>
#include <console.h>
#include <errno.h>
#include <async.h>
#include <string.h>
#include <as.h>
 
#include <elf.h>
80,13 → 78,6
/** Buffer holding all arguments */
static char *arg_buf = NULL;
 
/** Number of preset files */
static int filc = 0;
/** Preset files vector */
static fdi_node_t **filv = NULL;
/** Buffer holding all preset files */
static fdi_node_t *fil_buf = NULL;
 
static elf_info_t prog_info;
static elf_info_t interp_info;
 
95,7 → 86,7
/** Used to limit number of connections to one. */
static bool connected;
 
static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
task_id_t task_id;
122,7 → 113,7
* @param rid
* @param request
*/
static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t len;
158,7 → 149,7
* @param rid
* @param request
*/
static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_size, arg_size;
231,70 → 222,6
ipc_answer_0(rid, EOK);
}
 
/** Receive a call setting preset files of the program to execute.
*
* @param rid
* @param request
*/
static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_size;
if (!ipc_data_write_receive(&callid, &buf_size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
if ((buf_size % sizeof(fdi_node_t)) != 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
if (fil_buf != NULL) {
free(fil_buf);
fil_buf = NULL;
}
if (filv != NULL) {
free(filv);
filv = NULL;
}
fil_buf = malloc(buf_size);
if (!fil_buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
ipc_data_write_finalize(callid, fil_buf, buf_size);
int count = buf_size / sizeof(fdi_node_t);
/* Allocate filvv */
filv = malloc((count + 1) * sizeof(fdi_node_t *));
if (filv == NULL) {
free(fil_buf);
ipc_answer_0(rid, ENOMEM);
return;
}
/*
* Fill filv with argument pointers
*/
int i;
for (i = 0; i < count; i++)
filv[i] = &fil_buf[i];
filc = count;
filv[count] = NULL;
ipc_answer_0(rid, EOK);
}
 
/** Load the previously selected program.
*
* @param rid
301,7 → 228,7
* @param request
* @return 0 on success, !0 on error.
*/
static int ldr_load(ipc_callid_t rid, ipc_call_t *request)
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
317,9 → 244,6
pcb.argc = argc;
pcb.argv = argv;
pcb.filc = filc;
pcb.filv = filv;
if (prog_info.interp == NULL) {
/* Statically linked program */
is_dyn_linked = false;
354,7 → 278,7
* @param request
* @return 0 on success, !0 on error.
*/
static void ldr_run(ipc_callid_t rid, ipc_call_t *request)
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
{
const char *cp;
367,15 → 291,17
/* Dynamically linked program */
DPRINTF("Run ELF interpreter.\n");
DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
console_close();
ipc_answer_0(rid, EOK);
program_run(interp_info.entry, &pcb);
} else {
/* Statically linked program */
console_close();
ipc_answer_0(rid, EOK);
program_run(prog_info.entry, &pcb);
}
}
 
/* Not reached */
}
 
384,7 → 310,7
* Receive and carry out commands (of which the last one should be
* to execute the loaded program).
*/
static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
412,22 → 338,19
case IPC_M_PHONE_HUNGUP:
exit(0);
case LOADER_GET_TASKID:
ldr_get_taskid(callid, &call);
loader_get_taskid(callid, &call);
continue;
case LOADER_SET_PATHNAME:
ldr_set_pathname(callid, &call);
loader_set_pathname(callid, &call);
continue;
case LOADER_SET_ARGS:
ldr_set_args(callid, &call);
loader_set_args(callid, &call);
continue;
case LOADER_SET_FILES:
ldr_set_files(callid, &call);
continue;
case LOADER_LOAD:
ldr_load(callid, &call);
loader_load(callid, &call);
continue;
case LOADER_RUN:
ldr_run(callid, &call);
loader_run(callid, &call);
/* Not reached */
default:
retval = ENOENT;
447,24 → 370,16
int main(int argc, char *argv[])
{
ipcarg_t phonead;
task_id_t id;
int rc;
 
connected = false;
 
/* Introduce this task to the NS (give it our task ID). */
id = task_get_id();
rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
if (rc != EOK)
return -1;
 
/* Set a handler of incomming connections. */
async_set_client_connection(ldr_connection);
async_set_client_connection(loader_connection);
/* Register at naming service. */
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
return -2;
 
return -1;
async_manager();
/* Never reached */
/branches/dynload/uspace/srv/loader/arch/ia32/ia32.s
46,4 → 46,4
# Save a tiny bit of stack space
pop %ebp
 
jmp *%eax
jmp %eax
/branches/dynload/uspace/srv/loader/elf_load.c
74,7 → 74,7
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
 
/** Read until the buffer is read in its entirety. */
static int my_read(int fd, void *buf, size_t len)
static int my_read(int fd, char *buf, size_t len)
{
int cnt = 0;
do {
329,26 → 329,21
int flags = 0;
uintptr_t bias;
uintptr_t base;
void *seg_ptr;
uintptr_t seg_addr;
size_t mem_sz;
int rc;
 
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
entry->p_memsz);
bias = elf->bias;
 
seg_addr = entry->p_vaddr + bias;
seg_ptr = (void *) seg_addr;
 
DPRINTF("Load segment at addr 0x%x, size 0x%x\n", seg_addr,
entry->p_memsz);
 
if (entry->p_align > 1) {
if ((entry->p_offset % entry->p_align) !=
(seg_addr % entry->p_align)) {
(entry->p_vaddr % entry->p_align)) {
DPRINTF("Align check 1 failed offset%%align=%d, "
"vaddr%%align=%d\n",
entry->p_offset % entry->p_align,
seg_addr % entry->p_align
entry->p_vaddr % entry->p_align
);
return EE_INVALID;
}
367,7 → 362,7
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
DPRINTF("Map to seg_addr=0x%x-0x%x.\n", seg_addr,
DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias,
entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
 
/*
383,7 → 378,7
}
 
DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
base + bias, mem_sz, flags, (uintptr_t)a);
entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
 
/*
* Load segment data
403,7 → 398,7
uint8_t *dp;
 
left = entry->p_filesz;
dp = seg_ptr;
dp = (uint8_t *)(entry->p_vaddr + bias);
 
while (left > 0) {
now = 16384;
427,7 → 422,7
if ((elf->flags & ELDF_RW) != 0) return EE_OK;
 
// printf("set area flags to %d\n", flags);
rc = as_area_change_flags(seg_ptr, flags);
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
if (rc != 0) {
DPRINTF("Failed to set memory area flags.\n");
return EE_MEMORY;
435,7 → 430,7
 
if (flags & AS_AREA_EXEC) {
/* Enforce SMC coherence for the segment */
if (smc_coherence(seg_ptr, entry->p_filesz))
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
return EE_MEMORY;
}
 
/branches/dynload/uspace/srv/fb/serial_console.c
43,9 → 43,8
#include <ipc/fb.h>
#include <bool.h>
#include <errno.h>
#include <io/color.h>
#include <io/style.h>
#include <string.h>
#include <console/color.h>
#include <console/style.h>
 
#include "../console/screenbuffer.h"
#include "main.h"
129,9 → 128,9
 
}
 
void serial_goto(const unsigned int col, const unsigned int row)
void serial_goto(const unsigned int row, const unsigned int col)
{
if ((col > scr_width) || (row > scr_height))
if ((row > scr_height) || (col > scr_width))
return;
char control[MAX_CONTROL];
154,7 → 153,7
void serial_scroll(int i)
{
if (i > 0) {
serial_goto(0, scr_height - 1);
serial_goto(scr_height - 1, 0);
while (i--)
serial_puts("\033D");
} else if (i < 0) {
236,24 → 235,17
if (fgcolor < bgcolor)
serial_sgr(SGR_REVERSE_OFF);
else
serial_sgr(SGR_REVERSE);
serial_sgr(SGR_REVERSE);
}
 
static void serial_set_attrs(const attrs_t *a)
{
switch (a->t) {
case at_style:
serial_set_style(a->a.s.style);
break;
case at_rgb:
serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
break;
case at_idx:
serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
break;
default:
break;
case at_style: serial_set_style(a->a.s.style); break;
case at_rgb: serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color); break;
case at_idx: serial_set_idx(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags); break;
default: break;
}
}
 
273,13 → 265,13
keyfield_t *field;
attrs_t *a0, *a1;
 
serial_goto(x, y);
serial_goto(y, x);
a0 = &data[0].attrs;
serial_set_attrs(a0);
 
for (j = 0; j < h; j++) {
if (j > 0 && w != scr_width)
serial_goto(x, j);
serial_goto(y, x);
 
for (i = 0; i < w; i++) {
field = &data[j * w + i];
362,16 → 354,16
break;
}
draw_text_data(interbuf, col, row, w, h);
lastrow = row + h - 1;
lastcol = col + w;
lastrow = row + h - 1;
retval = 0;
break;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if ((lastcol != col) || (lastrow != row))
serial_goto(col, row);
serial_goto(row, col);
lastcol = col + 1;
lastrow = row;
serial_putchar(c);
378,20 → 370,16
retval = 0;
break;
case FB_CURSOR_GOTO:
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
serial_goto(col, row);
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
serial_goto(row, col);
lastrow = row;
lastcol = col;
lastrow = row;
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_width, scr_height);
ipc_answer_2(callid, EOK, scr_height, scr_width);
continue;
case FB_GET_COLOR_CAP:
ipc_answer_1(callid, EOK, color ? FB_CCAP_INDEXED :
FB_CCAP_STYLE);
continue;
case FB_CLEAR:
serial_clrscr();
retval = 0;
428,7 → 416,7
break;
}
serial_scroll(i);
serial_goto(lastcol, lastrow);
serial_goto(lastrow, lastcol);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
457,6 → 445,6
}
}
 
/**
/**
* @}
*/
/branches/dynload/uspace/srv/fb/fb.c
51,13 → 51,10
#include <ipc/services.h>
#include <kernel/errno.h>
#include <kernel/genarch/fb/visuals.h>
#include <io/color.h>
#include <io/style.h>
#include <console/color.h>
#include <console/style.h>
#include <async.h>
#include <fibril.h>
#include <bool.h>
#include <stdio.h>
#include <byteorder.h>
 
#include "font-8x16.h"
#include "fb.h"
213,9 → 210,9
unsigned int row);
 
 
#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
 
#define COL2X(col) ((col) * FONT_WIDTH)
#define ROW2Y(row) ((row) * FONT_SCANLINES)
227,58 → 224,36
#define BB_POS(vport, col, row) ((row) * vport->cols + (col))
#define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline)
 
/*
* RGB conversion and mask functions.
 
/** ARGB 8:8:8:8 conversion
*
* These functions write an RGB value to some memory in some predefined format.
* The naming convention corresponds to the format created by these functions.
* The functions use the so called network order (i.e. big endian) with respect
* to their names.
*/
 
static void rgb_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
(RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
*((uint32_t *) dst) = rgb & 0x00ffffff;
}
 
static void bgr_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
(BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
}
 
static void mask_0888(void *dst, bool mask)
{
bgr_0888(dst, mask ? 0xffffff : 0);
*((uint32_t *) dst) = (mask ? 0x00ffffff : 0);
}
 
static void rgb_8880(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
(GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
}
 
static void bgr_8880(void *dst, uint32_t rgb)
/** ABGR 8:8:8:8 conversion
*
*/
static void bgr_0888(void *dst, uint32_t rgb)
{
*((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
(GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
*((uint32_t *) dst)
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
}
 
static void mask_8880(void *dst, bool mask)
{
bgr_8880(dst, mask ? 0xffffff : 0);
}
 
/** RGB 8:8:8 conversion
*
*/
static void rgb_888(void *dst, uint32_t rgb)
{
((uint8_t *) dst)[0] = RED(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = BLUE(rgb, 8);
}
 
static void bgr_888(void *dst, uint32_t rgb)
{
((uint8_t *) dst)[0] = BLUE(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = RED(rgb, 8);
286,44 → 261,63
 
static void mask_888(void *dst, bool mask)
{
bgr_888(dst, mask ? 0xffffff : 0);
if (mask) {
((uint8_t *) dst)[0] = 0xff;
((uint8_t *) dst)[1] = 0xff;
((uint8_t *) dst)[2] = 0xff;
} else {
((uint8_t *) dst)[0] = 0;
((uint8_t *) dst)[1] = 0;
((uint8_t *) dst)[2] = 0;
}
}
 
static void rgb_555_be(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
}
 
static void rgb_555_le(void *dst, uint32_t rgb)
/** BGR 8:8:8 conversion
*
*/
static void bgr_888(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
((uint8_t *) dst)[0] = RED(rgb, 8);
((uint8_t *) dst)[1] = GREEN(rgb, 8);
((uint8_t *) dst)[2] = BLUE(rgb, 8);
}
 
static void rgb_565_be(void *dst, uint32_t rgb)
 
/** RGB 5:5:5 conversion
*
*/
static void rgb_555(void *dst, uint32_t rgb)
{
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
*((uint16_t *) dst)
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
}
 
static void rgb_565_le(void *dst, uint32_t rgb)
static void mask_555(void *dst, bool mask)
{
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
*((uint16_t *) dst) = (mask ? 0x7fff : 0);
}
 
static void mask_555(void *dst, bool mask)
 
/** RGB 5:6:5 conversion
*
*/
static void rgb_565(void *dst, uint32_t rgb)
{
rgb_555_be(dst, mask ? 0xffffff : 0);
*((uint16_t *) dst)
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
}
 
static void mask_565(void *dst, bool mask)
{
rgb_565_be(dst, mask ? 0xffffff : 0);
*((uint16_t *) dst) = (mask ? 0xffff : 0);
}
 
static void bgr_323(void *dst, uint32_t rgb)
 
/** RGB 3:2:3
*
*/
static void rgb_323(void *dst, uint32_t rgb)
{
*((uint8_t *) dst)
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
331,7 → 325,7
 
static void mask_323(void *dst, bool mask)
{
bgr_323(dst, mask ? 0x0 : ~0x0);
*((uint8_t *) dst) = (mask ? 0xff : 0);
}
 
/** Draw a filled rectangle.
381,8 → 375,8
*/
static void vport_redraw(viewport_t *vport)
{
unsigned int row;
unsigned int col;
unsigned int row;
for (row = 0; row < vport->rows; row++) {
for (col = 0; col < vport->cols; col++) {
437,8 → 431,8
*/
static void vport_scroll(viewport_t *vport, int lines)
{
unsigned int row;
unsigned int col;
unsigned int row;
unsigned int x;
unsigned int y;
uint32_t glyph;
455,8 → 449,7
for (row = 0; row < vport->rows; row++) {
x = vport->x;
for (col = 0; col < vport->cols; col++) {
if (((int) row + lines >= 0) &&
((int) row + lines < (int) vport->rows)) {
if ((row + lines >= 0) && (row + lines < vport->rows)) {
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)];
bbp = &vport->backbuf[BB_POS(vport, col, row)];
625,32 → 618,24
static bool screen_init(void *addr, unsigned int xres, unsigned int yres,
unsigned int scan, unsigned int visual)
{
switch (visual) {
case VISUAL_INDIRECT_8:
screen.rgb_conv = bgr_323;
screen.rgb_conv = rgb_323;
screen.mask_conv = mask_323;
screen.pixelbytes = 1;
break;
case VISUAL_RGB_5_5_5_LE:
screen.rgb_conv = rgb_555_le;
case VISUAL_RGB_5_5_5:
screen.rgb_conv = rgb_555;
screen.mask_conv = mask_555;
screen.pixelbytes = 2;
break;
case VISUAL_RGB_5_5_5_BE:
screen.rgb_conv = rgb_555_be;
screen.mask_conv = mask_555;
screen.pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5_LE:
screen.rgb_conv = rgb_565_le;
case VISUAL_RGB_5_6_5:
screen.rgb_conv = rgb_565;
screen.mask_conv = mask_565;
screen.pixelbytes = 2;
break;
case VISUAL_RGB_5_6_5_BE:
screen.rgb_conv = rgb_565_be;
screen.mask_conv = mask_565;
screen.pixelbytes = 2;
break;
case VISUAL_RGB_8_8_8:
screen.rgb_conv = rgb_888;
screen.mask_conv = mask_888;
662,8 → 647,8
screen.pixelbytes = 3;
break;
case VISUAL_RGB_8_8_8_0:
screen.rgb_conv = rgb_8880;
screen.mask_conv = mask_8880;
screen.rgb_conv = rgb_888;
screen.mask_conv = mask_888;
screen.pixelbytes = 4;
break;
case VISUAL_RGB_0_8_8_8:
676,11 → 661,6
screen.mask_conv = mask_0888;
screen.pixelbytes = 4;
break;
case VISUAL_BGR_8_8_8_0:
screen.rgb_conv = bgr_8880;
screen.mask_conv = mask_8880;
screen.pixelbytes = 4;
break;
default:
return false;
}
1058,8 → 1038,8
*
* @return false if the call was not handled byt this function, true otherwise
*
* Note: this function is not thread-safe, you would have
* to redefine static variables with fibril_local.
* Note: this function is not threads safe, you would have
* to redefine static variables with __thread
*
*/
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
1085,11 → 1065,10
if (IPC_GET_ARG1(*call) == shm_id) {
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
shm_size = IPC_GET_ARG2(*call);
if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) {
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
shm = dest;
else
shm_id = 0;
return false;
}
shm = dest;
if (shm[0] != 'P')
return false;
1585,7 → 1564,7
unsigned int i;
int scroll;
wchar_t ch;
unsigned int col, row;
unsigned int row, col;
if ((vport->cursor_active) || (anims_enabled))
callid = async_get_call_timeout(&call, 250000);
1622,8 → 1601,8
case FB_PUTCHAR:
ch = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
1641,8 → 1620,8
retval = EOK;
break;
case FB_CURSOR_GOTO:
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
if ((col >= vport->cols) || (row >= vport->rows)) {
retval = EINVAL;
1662,11 → 1641,8
retval = EOK;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, vport->cols, vport->rows);
ipc_answer_2(callid, EOK, vport->rows, vport->cols);
continue;
case FB_GET_COLOR_CAP:
ipc_answer_1(callid, EOK, FB_CCAP_RGB);
continue;
case FB_SCROLL:
scroll = IPC_GET_ARG1(call);
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) {
1761,17 → 1737,17
unsigned int fb_height = sysinfo_value("fb.height");
unsigned int fb_scanline = sysinfo_value("fb.scanline");
unsigned int fb_visual = sysinfo_value("fb.visual");
 
unsigned int fbsize = fb_scanline * fb_height;
void *fb_addr = as_get_mappable_page(fbsize);
 
if (physmem_map(fb_ph_addr + fb_offset, fb_addr,
ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
return -1;
 
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual))
return 0;
 
return -1;
}
 
/branches/dynload/uspace/srv/fb/ega.c
49,8 → 49,8
#include <ipc/ns.h>
#include <ipc/services.h>
#include <libarch/ddi.h>
#include <io/style.h>
#include <io/color.h>
#include <console/style.h>
#include <console/color.h>
#include <sys/types.h>
 
#include "ega.h"
70,7 → 70,7
int ega_normal_color = 0x0f;
int ega_inverted_color = 0xf0;
 
#define NORMAL_COLOR ega_normal_color
#define NORMAL_COLOR ega_normal_color
#define INVERTED_COLOR ega_inverted_color
 
/* Allow only 1 connection */
87,7 → 87,7
 
static void clrscr(void)
{
unsigned i;
int i;
for (i = 0; i < scr_width * scr_height; i++) {
scr_addr[i * 2] = ' ';
95,7 → 95,7
}
}
 
static void cursor_goto(unsigned int col, unsigned int row)
static void cursor_goto(unsigned int row, unsigned int col)
{
int ega_cursor;
 
129,8 → 129,7
 
static void scroll(int rows)
{
unsigned i;
 
int i;
if (rows > 0) {
memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
scr_width * scr_height * 2 - rows * scr_width * 2);
145,12 → 144,12
}
}
 
static void printchar(wchar_t c, unsigned int col, unsigned int row)
static void printchar(wchar_t c, unsigned int row, unsigned int col)
{
scr_addr[(row * scr_width + col) * 2] = ega_glyph(c);
scr_addr[(row * scr_width + col) * 2 + 1] = style;
cursor_goto(col + 1, row);
cursor_goto(row, col + 1);
}
 
/** Draw text data to viewport.
242,15 → 241,11
static unsigned attr_to_ega_style(const attrs_t *a)
{
switch (a->t) {
case at_style:
return style_to_ega_style(a->a.s.style);
case at_rgb:
return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
case at_idx:
return color_to_ega_style(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
default:
return INVERTED_COLOR;
case at_style: return style_to_ega_style(a->a.s.style);
case at_rgb: return rgb_to_ega_style(a->a.r.fg_color, a->a.r.bg_color);
case at_idx: return color_to_ega_style(a->a.i.fg_color,
a->a.i.bg_color, a->a.i.flags);
default: return INVERTED_COLOR;
}
}
 
317,11 → 312,8
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, scr_width, scr_height);
ipc_answer_2(callid, EOK, scr_height, scr_width);
continue;
case FB_GET_COLOR_CAP:
ipc_answer_1(callid, EOK, FB_CCAP_INDEXED);
continue;
case FB_CLEAR:
clrscr();
retval = 0;
328,28 → 320,28
break;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
row = IPC_GET_ARG3(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
if (col >= scr_width || row >= scr_height) {
retval = EINVAL;
break;
}
printchar(c, col, row);
printchar(c, row, col);
retval = 0;
break;
case FB_CURSOR_GOTO:
col = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
row = IPC_GET_ARG1(call);
col = IPC_GET_ARG2(call);
if (row >= scr_height || col >= scr_width) {
retval = EINVAL;
break;
}
cursor_goto(col, row);
cursor_goto(row, col);
retval = 0;
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if (i > (int) scr_height || i < -((int) scr_height)) {
if (i > scr_height || i < -((int) scr_height)) {
retval = EINVAL;
break;
}
/branches/dynload/uspace/srv/fb/serial_console.h
43,7 → 43,7
typedef void (*putc_function_t)(char);
 
void serial_puts(char *str);
void serial_goto(const unsigned int col, const unsigned int row);
void serial_goto(const unsigned int row, const unsigned int col);
void serial_clrscr(void);
void serial_scroll(int i);
void serial_cursor_disable(void);
/branches/dynload/uspace/srv/fb/Makefile
34,8 → 34,10
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
CFLAGS += -I../libipc/include
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
103,7 → 105,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/fb/ppm.c
89,7 → 89,7
{
unsigned int width, height;
unsigned int maxcolor;
unsigned int i;
int i;
unsigned int color;
unsigned int coef;
/branches/dynload/uspace/srv/fb/ega.h
27,10 → 27,10
*/
 
/** @addtogroup egafb
* @brief HelenOS EGA framebuffer.
* @brief HelenOS EGA framebuffer.
* @ingroup fbs
* @{
*/
*/
/** @file
*/
 
43,3 → 43,4
 
/** @}
*/
 
/branches/dynload/uspace/srv/devmap/devmap.c
41,81 → 41,67
#include <stdio.h>
#include <errno.h>
#include <bool.h>
#include <fibril_sync.h>
#include <futex.h>
#include <stdlib.h>
#include <string.h>
#include <ipc/devmap.h>
 
#define NAME "devmap"
#define NULL_DEVICES 256
#define NAME "devmap"
 
/** Representation of device driver.
*
* Each driver is responsible for a set of devices.
*
*/
/** Pending lookup structure. */
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;
/** Fibril mutex for list of devices owned by this driver */
fibril_mutex_t devices_mutex;
} devmap_driver_t;
link_t link;
char *name; /**< Device name */
ipc_callid_t callid; /**< Call ID waiting for the lookup */
} pending_req_t;
 
/** Info about registered device
*
*/
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 */
dev_handle_t handle;
/** Device name */
char *name;
/** Device driver handling this device */
devmap_driver_t *driver;
} devmap_device_t;
 
LIST_INITIALIZE(devices_list);
LIST_INITIALIZE(drivers_list);
LIST_INITIALIZE(pending_req);
 
/* Locking order:
* drivers_list_mutex
* devices_list_mutex
* (devmap_driver_t *)->devices_mutex
* create_handle_mutex
* drivers_list_futex
* devices_list_futex
* (devmap_driver_t *)->devices_futex
* create_handle_futex
**/
 
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
static atomic_t devices_list_futex = FUTEX_INITIALIZER;
static atomic_t drivers_list_futex = FUTEX_INITIALIZER;
static atomic_t create_handle_futex = FUTEX_INITIALIZER;
 
static dev_handle_t last_handle = 0;
static devmap_device_t *null_devices[NULL_DEVICES];
 
static dev_handle_t devmap_create_handle(void)
static int devmap_create_handle(void)
{
static int last_handle = 0;
int handle;
/* TODO: allow reusing old handles after their unregistration
* and implement some version of LRU algorithm, avoid overflow
* and implement some version of LRU algorithm
*/
fibril_mutex_lock(&create_handle_mutex);
last_handle++;
fibril_mutex_unlock(&create_handle_mutex);
/* FIXME: overflow */
futex_down(&create_handle_futex);
return last_handle;
last_handle += 1;
handle = last_handle;
futex_up(&create_handle_futex);
return handle;
}
 
 
/** Initialize device mapper.
*
*
*/
static int devmap_init()
{
/* TODO: */
return EOK;
}
 
/** Find device with given name.
*
*/
126,7 → 112,7
while (item != &devices_list) {
device = list_get_instance(item, devmap_device_t, devices);
if (str_cmp(device->name, name) == 0)
if (0 == str_cmp(device->name, name))
break;
item = item->next;
}
143,9 → 129,9
* @todo: use hash table
*
*/
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
static devmap_device_t *devmap_device_find_handle(int handle)
{
fibril_mutex_lock(&devices_list_mutex);
futex_down(&devices_list_futex);
link_t *item = (&devices_list)->next;
devmap_device_t *device = NULL;
158,20 → 144,22
}
if (item == &devices_list) {
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&devices_list_futex);
return NULL;
}
device = list_get_instance(item, devmap_device_t, devices);
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&devices_list_futex);
return device;
}
 
/**
*
* Unregister device and free it. It's assumed that driver's device list is
* already locked.
*
*/
static int devmap_device_unregister_core(devmap_device_t *device)
{
185,8 → 173,10
}
 
/**
*
* Read info about new driver and add it into linked list of registered
* drivers.
*
*/
static void devmap_driver_register(devmap_driver_t **odriver)
{
240,7 → 230,7
/*
* Send confirmation to sender and get data into buffer.
*/
if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
free(driver->name);
free(driver);
ipc_answer_0(iid, EREFUSED);
249,21 → 239,21
driver->name[name_size] = 0;
/* Initialize mutex for list of devices owned by this driver */
fibril_mutex_initialize(&driver->devices_mutex);
/* Initialize futex for list of devices owned by this driver */
futex_initialize(&(driver->devices_futex), 1);
/*
* Initialize list of asociated devices
*/
list_initialize(&driver->devices);
list_initialize(&(driver->devices));
/*
* Create connection to the driver
* Create connection to the driver
*/
ipc_call_t call;
callid = async_get_call(&call);
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
ipc_answer_0(callid, ENOTSUP);
free(driver->name);
278,7 → 268,7
list_initialize(&(driver->drivers));
fibril_mutex_lock(&drivers_list_mutex);
futex_down(&drivers_list_futex);
/* TODO:
* check that no driver with name equal to driver->name is registered
288,7 → 278,7
* Insert new driver into list of registered drivers
*/
list_append(&(driver->drivers), &drivers_list);
fibril_mutex_unlock(&drivers_list_mutex);
futex_up(&drivers_list_futex);
ipc_answer_0(iid, EOK);
305,18 → 295,18
if (driver == NULL)
return EEXISTS;
fibril_mutex_lock(&drivers_list_mutex);
futex_down(&drivers_list_futex);
if (driver->phone != 0)
ipc_hangup(driver->phone);
ipc_hangup(driver->phone);
/* Remove it from list of drivers */
/* remove it from list of drivers */
list_remove(&(driver->drivers));
/* Unregister all its devices */
fibril_mutex_lock(&devices_list_mutex);
fibril_mutex_lock(&driver->devices_mutex);
/* unregister all its devices */
futex_down(&devices_list_futex);
futex_down(&(driver->devices_futex));
while (!list_empty(&(driver->devices))) {
devmap_device_t *device = list_get_instance(driver->devices.next,
devmap_device_t, driver_devices);
323,12 → 313,12
devmap_device_unregister_core(device);
}
fibril_mutex_unlock(&driver->devices_mutex);
fibril_mutex_unlock(&devices_list_mutex);
fibril_mutex_unlock(&drivers_list_mutex);
futex_up(&(driver->devices_futex));
futex_up(&devices_list_futex);
futex_up(&drivers_list_futex);
/* free name and driver */
if (driver->name != NULL)
if (NULL != driver->name)
free(driver->name);
free(driver);
336,6 → 326,30
return EOK;
}
 
 
/** Process pending lookup requests */
static void process_pending_lookup()
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
const devmap_device_t *dev = devmap_device_find_name(pr->name);
if (!dev)
continue;
ipc_answer_1(pr->callid, EOK, dev->handle);
free(pr->name);
list_remove(cur);
free(pr);
goto loop;
}
}
 
 
/** Register instance of device
*
*/
386,12 → 400,12
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
fibril_mutex_lock(&devices_list_mutex);
futex_down(&devices_list_futex);
/* Check that device with such name is not already registered */
if (NULL != devmap_device_find_name(device->name)) {
printf(NAME ": Device '%s' already registered\n", device->name);
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&devices_list_futex);
free(device->name);
free(device);
ipc_answer_0(iid, EEXISTS);
407,15 → 421,16
list_append(&device->devices, &devices_list);
/* Insert device into list of devices that belog to one driver */
fibril_mutex_lock(&device->driver->devices_mutex);
futex_down(&device->driver->devices_futex);
list_append(&device->driver_devices, &device->driver->devices);
fibril_mutex_unlock(&device->driver->devices_mutex);
fibril_condvar_broadcast(&devices_list_cv);
fibril_mutex_unlock(&devices_list_mutex);
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
ipc_answer_1(iid, EOK, device->handle);
process_pending_lookup();
}
 
/**
439,15 → 454,15
/*
* Get handle from request
*/
dev_handle_t handle = IPC_GET_ARG2(*call);
int handle = IPC_GET_ARG2(*call);
devmap_device_t *dev = devmap_device_find_handle(handle);
if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
if (NULL == dev) {
ipc_answer_0(callid, ENOENT);
return;
}
ipc_forward_fast(callid, dev->driver->phone, dev->handle,
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
}
 
480,7 → 495,7
/*
* Allocate buffer for device name.
*/
char *name = (char *) malloc(size + 1);
char *name = (char *) malloc(size);
if (name == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
498,14 → 513,10
}
name[size] = '\0';
fibril_mutex_lock(&devices_list_mutex);
const devmap_device_t *dev;
recheck:
 
/*
* Find device name in the list of known devices.
* Find device name in linked list of known devices.
*/
dev = devmap_device_find_name(name);
const devmap_device_t *dev = devmap_device_find_name(name);
/*
* Device was not found.
512,18 → 523,24
*/
if (dev == NULL) {
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
/* Blocking lookup */
fibril_condvar_wait(&devices_list_cv,
&devices_list_mutex);
goto recheck;
/* Blocking lookup, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(iid, ENOMEM);
free(name);
return;
}
pr->name = name;
pr->callid = iid;
list_append(&pr->link, &pending_req);
return;
}
ipc_answer_0(iid, ENOENT);
free(name);
fibril_mutex_unlock(&devices_list_mutex);
return;
}
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, dev->handle);
free(name);
532,7 → 549,7
/** Find name of device identified by id and send it to caller.
*
*/
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
{
const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
546,12 → 563,12
ipc_answer_0(iid, EOK);
size_t name_size = str_size(device->name);
/* FIXME:
* We have no channel from DEVMAP to client, therefore
* sending must be initiated by client.
*
* size_t name_size = str_size(device->name);
*
* int rc = ipc_data_write_send(phone, device->name, name_size);
* if (rc != EOK) {
* async_wait_for(req, NULL);
562,160 → 579,6
/* TODO: send name in response */
}
 
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&devices_list_mutex);
ipc_answer_1(iid, EOK, list_count(&devices_list));
fibril_mutex_unlock(&devices_list_mutex);
}
 
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&devices_list_mutex);
ipc_callid_t callid;
size_t size;
if (!ipc_data_read_receive(&callid, &size)) {
ipc_answer_0(callid, EREFUSED);
ipc_answer_0(iid, EREFUSED);
return;
}
if ((size % sizeof(dev_desc_t)) != 0) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(iid, EREFUSED);
return;
}
size_t count = size / sizeof(dev_desc_t);
dev_desc_t *desc = (dev_desc_t *) malloc(size);
if (desc == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
return;
}
size_t pos = 0;
link_t *item = devices_list.next;
while ((item != &devices_list) && (pos < count)) {
devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
desc[pos].handle = device->handle;
str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
pos++;
item = item->next;
}
ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
if (retval != EOK) {
ipc_answer_0(iid, EREFUSED);
free(desc);
return;
}
free(desc);
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, pos);
}
 
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&null_devices_mutex);
unsigned int i;
bool fnd = false;
for (i = 0; i < NULL_DEVICES; i++) {
if (null_devices[i] == NULL) {
fnd = true;
break;
}
}
if (!fnd) {
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, ENOMEM);
return;
}
/* Create NULL device entry */
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
if (device == NULL) {
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, ENOMEM);
return;
}
char null[DEVMAP_NAME_MAXLEN];
snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
device->name = str_dup(null);
if (device->name == NULL) {
fibril_mutex_unlock(&null_devices_mutex);
free(device);
ipc_answer_0(iid, ENOMEM);
return;
}
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
fibril_mutex_lock(&devices_list_mutex);
/* Get unique device handle */
device->handle = devmap_create_handle();
device->driver = NULL;
/* Insert device into list of all devices
and into null devices array */
list_append(&device->devices, &devices_list);
null_devices[i] = device;
fibril_mutex_unlock(&devices_list_mutex);
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_1(iid, EOK, (ipcarg_t) i);
}
 
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&null_devices_mutex);
ipcarg_t i = IPC_GET_ARG1(*icall);
if (null_devices[i] == NULL) {
ipc_answer_0(iid, ENOENT);
return;
}
devmap_device_unregister_core(null_devices[i]);
null_devices[i] = NULL;
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, EOK);
}
 
/** Initialize device mapper.
*
*
*/
static bool devmap_init(void)
{
fibril_mutex_lock(&null_devices_mutex);
unsigned int i;
for (i = 0; i < NULL_DEVICES; i++)
null_devices[i] = NULL;
fibril_mutex_unlock(&null_devices_mutex);
return true;
}
 
/** Handle connection with device driver.
*
*/
724,7 → 587,7
/* Accept connection */
ipc_answer_0(iid, EOK);
devmap_driver_t *driver = NULL;
devmap_driver_t *driver = NULL;
devmap_driver_register(&driver);
if (NULL == driver)
738,6 → 601,7
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
/* Exit thread */
continue;
case DEVMAP_DRIVER_UNREGISTER:
if (NULL == driver)
757,7 → 621,7
devmap_get_handle(callid, &call);
break;
case DEVMAP_DEVICE_GET_NAME:
devmap_get_name(callid, &call);
devmap_get_handle(callid, &call);
break;
default:
if (!(callid & IPC_CALLID_NOTIFICATION))
765,7 → 629,7
}
}
if (driver != NULL) {
if (NULL != driver) {
/*
* Unregister the device driver and all its devices.
*/
790,25 → 654,15
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
cont = false;
/* Exit thread */
continue;
case DEVMAP_DEVICE_GET_HANDLE:
devmap_get_handle(callid, &call);
break;
case DEVMAP_DEVICE_GET_NAME:
/* TODO */
devmap_get_name(callid, &call);
break;
case DEVMAP_DEVICE_NULL_CREATE:
devmap_null_create(callid, &call);
break;
case DEVMAP_DEVICE_NULL_DESTROY:
devmap_null_destroy(callid, &call);
break;
case DEVMAP_DEVICE_GET_COUNT:
devmap_get_count(callid, &call);
break;
case DEVMAP_DEVICE_GET_DEVICES:
devmap_get_devices(callid, &call);
break;
default:
if (!(callid & IPC_CALLID_NOTIFICATION))
ipc_answer_0(callid, ENOENT);
835,7 → 689,7
break;
default:
/* No such interface */
ipc_answer_0(iid, ENOENT);
ipc_answer_0(iid, ENOENT);
}
}
 
846,7 → 700,7
{
printf(NAME ": HelenOS Device Mapper\n");
if (!devmap_init()) {
if (devmap_init() != 0) {
printf(NAME ": Error while initializing service\n");
return -1;
}
/branches/dynload/uspace/srv/devmap/Makefile
34,8 → 34,10
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
CFLAGS += -I../libipc/include
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
65,7 → 67,7
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< > $@
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/dynload/uspace/srv/obio/obio.c
0,0 → 1,158
/*
* 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 obio
* @{
*/
 
/**
* @file obio.c
* @brief OBIO driver.
*
* OBIO is a short for on-board I/O. On UltraSPARC IIi and systems with U2P,
* there is a piece of the root PCI bus controller address space, which
* contains interrupt mapping and clear registers for all on-board devices.
* Although UltraSPARC IIi and U2P are different in general, these registers can
* be found at the same addresses.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/bus.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <stdio.h>
#include <ipc/devmap.h>
 
#define NAME "obio"
 
#define OBIO_SIZE 0x1898
 
#define OBIO_IMR_BASE 0x200
#define OBIO_IMR(ino) (OBIO_IMR_BASE + ((ino) & INO_MASK))
 
#define OBIO_CIR_BASE 0x300
#define OBIO_CIR(ino) (OBIO_CIR_BASE + ((ino) & INO_MASK))
 
#define INO_MASK 0x1f
 
static void *base_phys;
static volatile uint64_t *base_virt;
 
/** Handle one connection to obio.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void obio_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
while (1) {
int inr;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case BUS_CLEAR_INTERRUPT:
inr = IPC_GET_ARG1(call);
base_virt[OBIO_CIR(inr & INO_MASK)] = 0;
ipc_answer_0(callid, EOK);
break;
default:
ipc_answer_0(callid, EINVAL);
break;
}
}
}
 
/** Initialize the OBIO driver.
*
* So far, the driver heavily depends on information provided by the kernel via
* sysinfo. In the future, there should be a standalone OBIO driver.
*/
static bool obio_init(void)
{
ipcarg_t phonead;
 
base_phys = (void *) sysinfo_value("obio.base.physical");
if (!base_phys) {
printf(NAME ": no OBIO registers found\n");
return false;
}
 
base_virt = as_get_mappable_page(OBIO_SIZE);
int flags = AS_AREA_READ | AS_AREA_WRITE;
int retval = physmem_map(base_phys, (void *) base_virt,
ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping OBIO registers\n");
return false;
}
printf(NAME ": OBIO registers with base at %p\n", base_phys);
 
async_set_client_connection(obio_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead);
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS OBIO driver\n");
if (!obio_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
Property changes:
Added: svn:mergeinfo
/branches/dynload/uspace/srv/obio/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 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.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = obio
SOURCES = \
obio.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dynload/uspace/srv/obio
Property changes:
Added: svn:mergeinfo
/branches/dynload/uspace/srv/fhc/fhc.c
0,0 → 1,157
/*
* 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 fhc
* @{
*/
 
/**
* @file fhc.c
* @brief FHC bus controller driver.
*/
 
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/bus.h>
#include <ipc/ns.h>
#include <sysinfo.h>
#include <as.h>
#include <ddi.h>
#include <align.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <align.h>
#include <async.h>
#include <stdio.h>
#include <ipc/devmap.h>
 
#define NAME "fhc"
 
#define FHC_UART_INR 0x39
 
#define FHC_UART_IMAP 0x0
#define FHC_UART_ICLR 0x4
 
static void *fhc_uart_phys;
static volatile uint32_t *fhc_uart_virt;
static size_t fhc_uart_size;
 
/** Handle one connection to fhc.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
 
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
ipc_answer_0(iid, EOK);
 
while (1) {
int inr;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case BUS_CLEAR_INTERRUPT:
inr = IPC_GET_ARG1(call);
switch (inr) {
case FHC_UART_INR:
fhc_uart_virt[FHC_UART_ICLR] = 0;
ipc_answer_0(callid, EOK);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
}
break;
default:
ipc_answer_0(callid, EINVAL);
break;
}
}
}
 
/** Initialize the FHC driver.
*
* So far, the driver heavily depends on information provided by the kernel via
* sysinfo. In the future, there should be a standalone FHC driver.
*/
static bool fhc_init(void)
{
ipcarg_t phonead;
 
fhc_uart_size = sysinfo_value("fhc.uart.size");
fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical");
if (!fhc_uart_size) {
printf(NAME ": no FHC UART registers found\n");
return false;
}
 
fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
int flags = AS_AREA_READ | AS_AREA_WRITE;
int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt,
ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
if (retval < 0) {
printf(NAME ": Error mapping FHC UART registers\n");
return false;
}
printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys,
fhc_uart_size);
 
async_set_client_connection(fhc_connection);
ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead);
return true;
}
 
int main(int argc, char **argv)
{
printf(NAME ": HelenOS FHC bus controller driver\n");
if (!fhc_init())
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
 
/* Never reached */
return 0;
}
 
/**
* @}
*/
/branches/dynload/uspace/srv/fhc/Makefile
0,0 → 1,76
#
# Copyright (c) 2006 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.
#
 
## Setup toolchain
#
 
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = fhc
SOURCES = \
fhc.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dynload/uspace/Makefile
38,18 → 38,14
lib/softint \
lib/softfloat \
lib/libtest \
srv/bd/ata_bd \
srv/bd/file_bd \
srv/bd/gxe_bd \
srv/bd/rd \
srv/ns \
srv/loader \
srv/fb \
srv/kbd \
srv/console \
srv/rd \
srv/fs/fat \
srv/fs/tmpfs \
srv/fs/devfs \
srv/vfs \
srv/devmap \
app/tetris \
59,7 → 55,6
app/trace \
app/klog \
app/init \
app/getvc \
app/bdsh
 
ifeq ($(UARCH),amd64)
72,8 → 67,8
 
ifeq ($(UARCH),sparc64)
DIRS += \
srv/cir/fhc \
srv/cir/obio
srv/fhc \
srv/obio
endif
 
ifeq ($(CONFIG_BUILD_SHARED_LIBC), y)
/branches/dynload/HelenOS.config
55,11 → 55,6
@ "serengeti" Serengeti system
! [PLATFORM=sparc64] MACHINE (choice)
 
% Machine type
@ "testarm" GXEmul Testarm
@ "integratorcp" Integratorcp
! [PLATFORM=arm32] MACHINE (choice)
 
% CPU type
@ "pentium4" Pentium 4
@ "pentium3" Pentium 3
287,7 → 282,7
## Kernel features options
 
% Support for SMP
! [(PLATFORM=ia32&PROCESSOR!=athlon_xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)] CONFIG_SMP (y/n)
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)] CONFIG_SMP (y/n)
 
% Debug build
! CONFIG_DEBUG (y/n)
295,6 → 290,12
% Deadlock detection support for spinlocks
! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n)
 
% Improved support for hyperthreading
! [PLATFORM=amd64&CONFIG_SMP=y] CONFIG_HT (y/n)
 
% Improved support for hyperthreading
! [PLATFORM=ia32&PROCESSOR!=athlon_xp&PROCESSOR!=athlon_mp&PROCESSOR!=pentium3&CONFIG_SMP=y] CONFIG_HT (y/n)
 
% Lazy FPU context switching
! [CONFIG_FPU=y] CONFIG_FPU_LAZY (y/n)
 
330,12 → 331,8
 
% Input device class
@ "generic" Keyboard or serial line
! [PLATFORM=arm32&MACHINE=integratorcp] CONFIG_HID_IN (choice)
 
% Input device class
@ "generic" Keyboard or serial line
@ "none" No input device
! [PLATFORM=ia32|(PLATFORM=arm32&MACHINE=testarm)|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice)
! [PLATFORM=ia32|PLATFORM=arm32|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice)
 
% Input device class
@ "generic" Keyboard or serial line
346,10 → 343,6
 
% Output device class
@ "generic" Monitor or serial line
! [PLATFORM=arm32&MACHINE=integratorcp] CONFIG_HID_OUT (choice)
 
% Output device class
@ "generic" Monitor or serial line
@ "none" No output device
! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ppc32|(PLATFORM=ia64&MACHINE=i460GX)|(PLATFORM=mips32&MACHINE=msim)] CONFIG_HID_OUT (choice)
 
365,7 → 358,7
@ "monitor" Monitor
@ "serial" Serial line
@ "none" No output device
! [PLATFORM=arm32&MACHINE=testarm] CONFIG_HID_OUT (choice)
! [PLATFORM=arm32] CONFIG_HID_OUT (choice)
 
% PC keyboard support
! [CONFIG_HID_IN=generic&(PLATFORM=ia32|PLATFORM=amd64)] CONFIG_PC_KBD (y/n)
380,10 → 373,10
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=mips32] CONFIG_MIPS_PRN (y/n)
 
% Support for GXemul keyboard
! [CONFIG_HID_IN=generic&PLATFORM=arm32&MACHINE=testarm] CONFIG_ARM_KBD (y/n)
! [CONFIG_HID_IN=generic&PLATFORM=arm32] CONFIG_ARM_KBD (y/n)
 
% Support for GXemul printer
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=testarm] CONFIG_ARM_PRN (y/n)
! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32] CONFIG_ARM_PRN (y/n)
 
% Support for VIA CUDA controller
! [CONFIG_HID_IN=generic&PLATFORM=ppc32] CONFIG_VIA_CUDA (y/n)
403,18 → 396,12
% Support for Serengeti keyboard
! [CONFIG_HID_IN=generic&PLATFORM=sparc64&MACHINE=serengeti] CONFIG_SGCN_KBD (y/n)
 
% Support for i8042 controller
% i8042 controller support
! [CONFIG_PC_KBD=y] CONFIG_I8042 (y)
 
% Support for pl050 controller
! [CONFIG_HID_IN=generic&PLATFORM=arm32&MACHINE=integratorcp] CONFIG_PL050 (y)
 
% Sun keyboard support
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic&(CONFIG_NS16550=y|CONFIG_Z8530=y)] CONFIG_SUN_KBD (y)
 
% Macintosh ADB keyboard support
! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=ppc32&(CONFIG_VIA_CUDA=y)] CONFIG_MAC_KBD (y)
 
% Dummy serial line input
! [CONFIG_MIPS_KBD=y|CONFIG_ARM_KBD=y] CONFIG_DSRLNIN (y)
 
482,9 → 469,3
% Link against shared C library
! [CONFIG_BUILD_SHARED_LIBC=y] CONFIG_USE_SHARED_LIBC (n/y)
! [CONFIG_BUILD_SHARED_LIBC=n] CONFIG_USE_SHARED_LIBC (n)
 
% Load disk drivers on startup
! CONFIG_START_BD (n/y)
 
% Mount /data on startup
! [CONFIG_START_BD=y] CONFIG_MOUNT_DATA (n/y)
/branches/dynload/boot/arch/ia32/Makefile.inc
33,7 → 33,7
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
47,14 → 47,10
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/ata_bd/ata_bd \
$(USPACEDIR)/srv/bd/file_bd/file_bd
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/dltest2/dltest2 \
/branches/dynload/boot/arch/sparc64/loader/Makefile
80,7 → 80,7
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
101,19 → 101,16
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/bd/file_bd/file_bd
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
 
ifeq ($(MACHINE),generic)
RD_SRVS += \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/cir/fhc/fhc \
$(USPACEDIR)/srv/cir/obio/obio
$(USPACEDIR)/srv/fhc/fhc \
$(USPACEDIR)/srv/obio/obio
endif
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/trace/trace \
$(USPACEDIR)/app/bdsh/bdsh \
/branches/dynload/boot/arch/ia64/loader/Makefile
87,7 → 87,7
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
100,13 → 100,10
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dynload/boot/arch/ia64/loader/types.h
41,4 → 41,7
typedef uint64_t uintptr_t;
typedef uint64_t unative_t;
 
typedef unsigned long count_t;
 
 
#endif
/branches/dynload/boot/arch/ppc32/loader/Makefile
75,7 → 75,7
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
88,13 → 88,10
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/dload/dload \
/branches/dynload/boot/arch/amd64/Makefile.inc
33,7 → 33,7
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
47,14 → 47,10
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/ata_bd/ata_bd \
$(USPACEDIR)/srv/bd/file_bd/file_bd
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dynload/boot/arch/mips32/loader/Makefile
88,7 → 88,7
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
101,14 → 101,10
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd \
$(USPACEDIR)/srv/bd/gxe_bd/gxe_bd
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/dload/dload \
/branches/dynload/boot/arch/arm32/loader/main.c
67,7 → 67,7
/** Prints bootloader version information. */
static void version_print(void)
{
printf("HelenOS ARM32 Bootloader\nRelease %s%s%s\nCopyright (c) 2009 HelenOS project\n",
printf("HelenOS ARM32 Bootloader\nRelease %s%s%s\nCopyright (c) 2007 HelenOS project\n",
release, revision, timestamp);
}
 
87,11 → 87,20
printf(" kernel entry point at %L\n", KERNEL_VIRTUAL_ADDRESS);
printf(" %L: boot info structure\n", &bootinfo);
 
unsigned int i, j;
for (i = 0; i < COMPONENTS; i++) {
printf(" %L: %s image (size %d bytes)\n",
components[i].start, components[i].name, components[i].size);
}
 
printf("\nCopying components\n");
 
unsigned int top = 0;
bootinfo.cnt = 0;
unsigned int i, j;
for (i = 0; i < COMPONENTS; i++) {
printf(" %s...", components[i].name);
top = ALIGN_UP(top, KERNEL_PAGE_SIZE);
memcpy(((void *) KERNEL_VIRTUAL_ADDRESS) + top, components[i].start, components[i].size);
if (i > 0) {
bootinfo.tasks[bootinfo.cnt].addr = ((void *) KERNEL_VIRTUAL_ADDRESS) + top;
bootinfo.tasks[bootinfo.cnt].size = components[i].size;
100,22 → 109,9
bootinfo.cnt++;
}
top += components[i].size;
printf("done.\n");
}
j = bootinfo.cnt - 1;
 
printf("\nCopying components\n");
printf("Component\tAddress\t\tSize (Bytes)\n");
printf("============================================\n");
for (i = COMPONENTS - 1; i > 0; i--, j--) {
printf("%s\t\t0x%x\t%d\n", components[i].name, bootinfo.tasks[j].addr, components[i].size);
memcpy((void *)bootinfo.tasks[j].addr, components[i].start,
components[i].size);
}
printf("KERNEL\t\t0x%x\t%d\n", KERNEL_VIRTUAL_ADDRESS, components[0].size);
 
memcpy((void *)KERNEL_VIRTUAL_ADDRESS, components[0].start,
components[0].size);
 
printf("\nBooting the kernel...\n");
jump_to_kernel((void *) KERNEL_VIRTUAL_ADDRESS, &bootinfo);
}
/branches/dynload/boot/arch/arm32/loader/Makefile
64,7 → 64,7
boot.S \
asm.S \
mm.c \
print/print.c \
print/gxemul.c \
_components.c \
../../../generic/printf.c \
../../../generic/string.c \
76,7 → 76,7
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/bd/rd/rd \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
89,17 → 89,10
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/devfs/devfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/bd/file_bd/file_bd
ifeq ($(MACHINE),testarm)
RD_SRVS += \
$(USPACEDIR)/srv/bd/gxe_bd/gxe_bd
endif
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/getvc/getvc \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/trace/trace \
/branches/dynload/boot/arch/arm32/loader/boot.S
34,10 → 34,8
.global start
.global jump_to_kernel
.global page_table
.global boot_stack
 
start:
ldr sp, =boot_stack
b bootstrap
 
jump_to_kernel:
48,10 → 46,6
#
bx r0
 
#bootloader stack
.section ST
.space 4096
boot_stack:
 
# place page_table to PT section
.section PT
/branches/dynload/boot/arch/arm32/loader/_link.ld.in
17,9 → 17,6
*(COMMON); /* global variables */
*(.reginfo);
 
. = 0x2000;
*(ST); /* bootloader stack section */
 
. = 0x4000;
*(PT); /* page table placed at 0x4000 */
[[COMPONENTS]]
/branches/dynload/boot/arch/arm32/loader/print/print.c
File deleted
Property changes:
Deleted: svn:mergeinfo
/branches/dynload/boot/arch/arm32/loader/print/gxemul.c
0,0 → 1,70
/*
* Copyright (c) 2007 Michal Kebrt
* 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 arm32boot
* @{
*/
/** @file
* @brief GXemul specific code.
*/
 
 
#include <printf.h>
 
 
/** Address where characters to be printed are expected. */
#define PUTC_ADDRESS 0x10000000
 
 
/** Prints a character to the console.
*
* @param ch Character to be printed.
*/
static void putc(char ch)
{
*((volatile char *) PUTC_ADDRESS) = ch;
}
 
 
/** Prints a string to the console.
*
* @param str String to be printed.
* @param len Number of characters to be printed.
*/
void write(const char *str, const int len)
{
int i;
for (i = 0; i < len; ++i) {
putc(str[i]);
}
}
 
/** @}
*/
 
/branches/dynload/defaults/sparc64/Makefile.config
57,9 → 57,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/defaults/ia64/Makefile.config
45,9 → 45,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/defaults/arm32/GXemul/Makefile.config
File deleted
/branches/dynload/defaults/arm32/integratorcp/Makefile.config
File deleted
/branches/dynload/defaults/arm32/Makefile.config
33,9 → 33,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/defaults/ppc32/Makefile.config
39,9 → 39,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/defaults/amd64/Makefile.config
16,6 → 16,9
# Support for SMP
CONFIG_SMP = y
 
# Improved support for hyperthreading
CONFIG_HT = y
 
# Lazy FPU context switching
CONFIG_FPU_LAZY = y
 
57,9 → 60,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/defaults/mips32/Makefile.config
39,9 → 39,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/defaults/ia32/Makefile.config
22,6 → 22,9
# Support for SMP
CONFIG_SMP = y
 
# Improved support for hyperthreading
CONFIG_HT = y
 
# Lazy FPU context switching
CONFIG_FPU_LAZY = y
 
63,9 → 66,3
 
# Use shared C library
CONFIG_SHARED_LIBC = n
 
# Load disk drivers on startup
CONFIG_START_BD = n
 
# Mount /data on startup
CONFIG_MOUNT_DATA = n
/branches/dynload/contrib/conf/ia32-qe.sh
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/branches/dynload/contrib/conf/mips32-gx.sh
1,10 → 1,3
#!/bin/sh
 
DISK_IMG=hdisk.img
 
# Create a disk image if it does not exist
if [ ! -f "$DISK_IMG" ]; then
tools/mkfat.py uspace/dist/data "$DISK_IMG"
fi
 
gxemul $@ -E testmips -C R4000 -X image.boot -d d0:"$DISK_IMG"
gxemul $@ -E testmips -C R4000 -X image.boot
/branches/dynload/version
36,7 → 36,7
 
VERSION = 0
PATCHLEVEL = 4
SUBLEVEL = 1
SUBLEVEL = 0
 
ifdef EXTRAVERSION
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL).$(EXTRAVERSION)
44,4 → 44,4
RELEASE = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)
endif
 
NAME = Escalopino
NAME = Sinister Valentine