/branches/dd/contrib/conf/mips32-gx.sh |
---|
1,3 → 1,10 |
#!/bin/sh |
gxemul $@ -E testmips -C R4000 -X image.boot |
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" |
/branches/dd/contrib/conf/ia32-qe.sh |
---|
0,0 → 1,10 |
#!/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 |
qemu -m 32 -hda "$DISK_IMG" -cdrom image.iso -boot d |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/dd/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, 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, 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). |
VADDR |
/branches/dd/kernel/genarch/include/kbrd/scanc_mac.h |
---|
0,0 → 1,48 |
/* |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for Macintosh ADB keyboards. |
*/ |
#ifndef KERN_SCANC_MAC_H_ |
#define KERN_SCANC_MAC_H_ |
#define SC_LSHIFT 0x38 |
#define SC_RSHIFT 0xfd /* Not used */ |
#define SC_CAPSLOCK 0xfe /* Not used */ |
#define SC_SCAN_ESCAPE 0xff /* Not used */ |
#endif |
/** @} |
*/ |
/branches/dd/kernel/genarch/include/drivers/via-cuda/cuda.h |
---|
38,14 → 38,80 |
#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/dd/kernel/genarch/Makefile.inc |
---|
110,6 → 110,12 |
genarch/src/kbrd/scanc_sun.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/dd/kernel/genarch/src/kbrd/kbrd.c |
---|
45,6 → 45,10 |
#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/dd/kernel/genarch/src/kbrd/scanc_mac.c |
---|
0,0 → 1,306 |
/* |
* 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 genarch |
* @{ |
*/ |
/** |
* @file |
* @brief Scan codes for Macintosh ADB keyboards. |
*/ |
#include <genarch/kbrd/scanc.h> |
#include <typedefs.h> |
#include <string.h> |
/** Primary meaning of scancodes. */ |
wchar_t sc_primary_map[SCANCODES] = { |
[0x00] = 'a', |
[0x01] = 's', |
[0x02] = 'd', |
[0x03] = 'f', |
[0x04] = 'h', |
[0x05] = 'g', |
[0x06] = 'z', |
[0x07] = 'x', |
[0x08] = 'c', |
[0x09] = 'v', |
[0x0a] = U_SPECIAL, |
[0x0b] = 'b', |
[0x0c] = 'q', |
[0x0d] = 'w', |
[0x0e] = 'e', |
[0x0f] = 'r', |
[0x10] = 'y', |
[0x11] = 't', |
[0x12] = '1', |
[0x13] = '2', |
[0x14] = '3', |
[0x15] = '4', |
[0x16] = '6', |
[0x17] = '5', |
[0x18] = '=', |
[0x19] = '9', |
[0x1a] = '7', |
[0x1b] = '-', |
[0x1c] = '8', |
[0x1d] = '0', |
[0x1e] = ']', |
[0x1f] = 'o', |
[0x20] = 'u', |
[0x21] = '[', |
[0x22] = 'i', |
[0x23] = 'p', |
[0x24] = '\n', /* Enter */ |
[0x25] = 'l', |
[0x26] = 'j', |
[0x27] = '\'', |
[0x28] = 'k', |
[0x29] = ';', |
[0x2a] = '\\', |
[0x2b] = ',', |
[0x2c] = '/', |
[0x2d] = 'n', |
[0x2e] = 'm', |
[0x2f] = '.', |
[0x30] = '\t', /* Tab */ |
[0x31] = ' ', /* Space */ |
[0x32] = '`', |
[0x33] = '\b', /* Backspace */ |
[0x34] = U_SPECIAL, |
[0x35] = U_ESCAPE, |
[0x36] = U_SPECIAL, |
[0x37] = U_SPECIAL, |
[0x38] = U_SPECIAL, |
[0x39] = U_SPECIAL, |
[0x3a] = U_SPECIAL, |
[0x3b] = U_LEFT_ARROW, |
[0x3c] = U_RIGHT_ARROW, |
[0x3d] = U_DOWN_ARROW, |
[0x3e] = U_UP_ARROW, |
[0x3f] = U_SPECIAL, |
[0x40] = U_SPECIAL, |
[0x41] = '.', /* Num Separator */ |
[0x42] = U_SPECIAL, |
[0x43] = '*', /* Num Times */ |
[0x44] = U_SPECIAL, |
[0x45] = '+', /* Num Plus */ |
[0x46] = U_SPECIAL, |
[0x47] = U_SPECIAL, |
[0x48] = U_SPECIAL, |
[0x49] = U_SPECIAL, |
[0x4a] = U_SPECIAL, |
[0x4b] = '/', /* Num Divide */ |
[0x4c] = U_SPECIAL, |
[0x4d] = U_SPECIAL, |
[0x4e] = '-', /* Num Minus */ |
[0x4f] = U_SPECIAL, |
[0x50] = U_SPECIAL, |
[0x51] = U_SPECIAL, |
[0x52] = '0', /* Num Zero */ |
[0x53] = '1', /* Num One */ |
[0x54] = '2', /* Num Two */ |
[0x55] = '3', /* Num Three */ |
[0x56] = '4', /* Num Four */ |
[0x57] = '5', /* Num Five */ |
[0x58] = '6', /* Num Six */ |
[0x59] = '7', /* Num Seven */ |
[0x5a] = U_SPECIAL, |
[0x5b] = '8', /* Num Eight */ |
[0x5c] = '9', /* Num Nine */ |
[0x5d] = U_SPECIAL, |
[0x5e] = U_SPECIAL, |
[0x5f] = U_SPECIAL, |
[0x60] = U_SPECIAL, |
[0x61] = U_SPECIAL, |
[0x62] = U_SPECIAL, |
[0x63] = U_SPECIAL, |
[0x64] = U_SPECIAL, |
[0x65] = U_SPECIAL, |
[0x66] = U_SPECIAL, |
[0x67] = U_SPECIAL, |
[0x68] = U_SPECIAL, |
[0x69] = U_SPECIAL, |
[0x6a] = U_SPECIAL, |
[0x6b] = U_SPECIAL, |
[0x6c] = U_SPECIAL, |
[0x6d] = U_SPECIAL, |
[0x6e] = U_SPECIAL, |
[0x6f] = U_SPECIAL, |
[0x70] = U_SPECIAL, |
[0x71] = U_SPECIAL, |
[0x72] = U_SPECIAL, |
[0x73] = U_HOME_ARROW, |
[0x74] = U_PAGE_UP, |
[0x75] = U_DELETE, |
[0x76] = U_SPECIAL, |
[0x77] = U_SPECIAL, |
[0x78] = U_SPECIAL, |
[0x79] = U_PAGE_DOWN, |
[0x7a] = U_SPECIAL, |
[0x7b] = U_SPECIAL, |
[0x7c] = U_SPECIAL, |
[0x7d] = U_SPECIAL, |
[0x7e] = U_SPECIAL, |
[0x7f] = U_SPECIAL |
}; |
/** Secondary meaning of scancodes. */ |
wchar_t sc_secondary_map[SCANCODES] = { |
[0x00] = 'A', |
[0x01] = 'S', |
[0x02] = 'D', |
[0x03] = 'F', |
[0x04] = 'H', |
[0x05] = 'G', |
[0x06] = 'Z', |
[0x07] = 'X', |
[0x08] = 'C', |
[0x09] = 'V', |
[0x0a] = U_SPECIAL, |
[0x0b] = 'B', |
[0x0c] = 'Q', |
[0x0d] = 'W', |
[0x0e] = 'E', |
[0x0f] = 'R', |
[0x10] = 'Y', |
[0x11] = 'T', |
[0x12] = '!', |
[0x13] = '@', |
[0x14] = '#', |
[0x15] = '$', |
[0x16] = '^', |
[0x17] = '%', |
[0x18] = '+', |
[0x19] = '(', |
[0x1a] = '&', |
[0x1b] = '_', |
[0x1c] = '*', |
[0x1d] = ')', |
[0x1e] = '}', |
[0x1f] = 'O', |
[0x20] = 'U', |
[0x21] = '{', |
[0x22] = 'I', |
[0x23] = 'P', |
[0x24] = '\n', /* Enter */ |
[0x25] = 'L', |
[0x26] = 'J', |
[0x27] = '"', |
[0x28] = 'K', |
[0x29] = ':', |
[0x2a] = '|', |
[0x2b] = '<', |
[0x2c] = '?', |
[0x2d] = 'N', |
[0x2e] = 'M', |
[0x2f] = '>', |
[0x30] = '\t', /* Tab */ |
[0x31] = ' ', /* Space */ |
[0x32] = '~', |
[0x33] = '\b', /* Backspace */ |
[0x34] = U_SPECIAL, |
[0x35] = U_SPECIAL, |
[0x36] = U_SPECIAL, |
[0x37] = U_SPECIAL, |
[0x38] = U_SPECIAL, |
[0x39] = U_SPECIAL, |
[0x3a] = U_SPECIAL, |
[0x3b] = U_SPECIAL, |
[0x3c] = U_SPECIAL, |
[0x3d] = U_SPECIAL, |
[0x3e] = U_SPECIAL, |
[0x3f] = U_SPECIAL, |
[0x40] = U_SPECIAL, |
[0x41] = '.', /* Num Separator */ |
[0x42] = U_SPECIAL, |
[0x43] = '*', /* Num Times */ |
[0x44] = U_SPECIAL, |
[0x45] = '+', /* Num Plus */ |
[0x46] = U_SPECIAL, |
[0x47] = U_SPECIAL, |
[0x48] = U_SPECIAL, |
[0x49] = U_SPECIAL, |
[0x4a] = U_SPECIAL, |
[0x4b] = '/', /* Num Divide */ |
[0x4c] = U_SPECIAL, |
[0x4d] = U_SPECIAL, |
[0x4e] = '-', /* Num Minus */ |
[0x4f] = U_SPECIAL, |
[0x50] = U_SPECIAL, |
[0x51] = U_SPECIAL, |
[0x52] = '0', /* Num Zero */ |
[0x53] = '1', /* Num One */ |
[0x54] = '2', /* Num Two */ |
[0x55] = '3', /* Num Three */ |
[0x56] = '4', /* Num Four */ |
[0x57] = '5', /* Num Five */ |
[0x58] = '6', /* Num Six */ |
[0x59] = '7', /* Num Seven */ |
[0x5a] = U_SPECIAL, |
[0x5b] = '8', /* Num Eight */ |
[0x5c] = '9', /* Num Nine */ |
[0x5d] = U_SPECIAL, |
[0x5e] = U_SPECIAL, |
[0x5f] = U_SPECIAL, |
[0x60] = U_SPECIAL, |
[0x61] = U_SPECIAL, |
[0x62] = U_SPECIAL, |
[0x63] = U_SPECIAL, |
[0x64] = U_SPECIAL, |
[0x65] = U_SPECIAL, |
[0x66] = U_SPECIAL, |
[0x67] = U_SPECIAL, |
[0x68] = U_SPECIAL, |
[0x69] = U_SPECIAL, |
[0x6a] = U_SPECIAL, |
[0x6b] = U_SPECIAL, |
[0x6c] = U_SPECIAL, |
[0x6d] = U_SPECIAL, |
[0x6e] = U_SPECIAL, |
[0x6f] = U_SPECIAL, |
[0x70] = U_SPECIAL, |
[0x71] = U_SPECIAL, |
[0x72] = U_SPECIAL, |
[0x73] = U_SPECIAL, |
[0x74] = U_SPECIAL, |
[0x75] = U_SPECIAL, |
[0x76] = U_SPECIAL, |
[0x77] = U_SPECIAL, |
[0x78] = U_SPECIAL, |
[0x79] = U_SPECIAL, |
[0x7a] = U_SPECIAL, |
[0x7b] = U_SPECIAL, |
[0x7c] = U_SPECIAL, |
[0x7d] = U_SPECIAL, |
[0x7e] = U_SPECIAL, |
[0x7f] = U_SPECIAL |
}; |
/** @} |
*/ |
/branches/dd/kernel/genarch/src/mm/page_ht.c |
---|
192,6 → 192,8 |
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/dd/kernel/genarch/src/acpi/acpi.c |
---|
167,10 → 167,13 |
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"); |
181,8 → 184,10 |
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/dd/kernel/genarch/src/drivers/via-cuda/cuda.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2006 Martin Decky |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
38,16 → 39,53 |
#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) |
{ |
return IRQ_DECLINE; |
} |
static irq_ownership_t cuda_claim(irq_t *irq); |
static void cuda_irq_handler(irq_t *irq); |
static void cuda_irq_handler(irq_t *irq) |
{ |
} |
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_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 |
55,7 → 93,15 |
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; |
64,15 → 110,251 |
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/dd/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,48 → 35,47 |
#ifndef KERN_BYTEORDER_H_ |
#define KERN_BYTEORDER_H_ |
#include <arch/byteorder.h> |
#include <arch/types.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
#if !(defined(__BE__) ^ defined(__LE__)) |
#error The architecture must be either big-endian or little-endian. |
#endif |
#ifdef ARCH_IS_BIG_ENDIAN |
#ifdef __BE__ |
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_le2host(n) (uint16_t_byteorder_swap(n)) |
#define uint32_t_le2host(n) (uint32_t_byteorder_swap(n)) |
#define uint64_t_le2host(n) (uint64_t_byteorder_swap(n)) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_le(n) (uint16_t_byteorder_swap(n)) |
#define host2uint32_t_le(n) (uint32_t_byteorder_swap(n)) |
#define host2uint64_t_le(n) (uint64_t_byteorder_swap(n)) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_be2host(n) (uint16_t_byteorder_swap(n)) |
#define uint32_t_be2host(n) (uint32_t_byteorder_swap(n)) |
#define uint64_t_be2host(n) (uint64_t_byteorder_swap(n)) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_be(n) (uint16_t_byteorder_swap(n)) |
#define host2uint32_t_be(n) (uint32_t_byteorder_swap(n)) |
#define host2uint64_t_be(n) (uint64_t_byteorder_swap(n)) |
#endif |
/branches/dd/kernel/generic/include/string.h |
---|
57,8 → 57,6 |
#define U_CURSOR 0x2588 |
#define U_BOM 0xfeff |
/**< No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
/branches/dd/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); |
extern int context_save_arch(context_t *c) __attribute__ ((returns_twice)); |
extern void context_restore_arch(context_t *c) __attribute__ ((noreturn)); |
/** Save register context. |
76,10 → 76,6 |
* 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/dd/kernel/generic/src/main/uinit.c |
---|
79,6 → 79,14 |
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/dd/kernel/generic/src/printf/printf_core.c |
---|
302,9 → 302,6 |
if (str == NULL) |
return printf_putstr(nullstr, ps); |
if (*str == U_BOM) |
str++; |
/* Print leading spaces. */ |
size_t strw = wstr_length(str); |
if (precision == 0) |
/branches/dd/kernel/Makefile |
---|
44,12 → 44,12 |
## Common compiler flags |
# |
DEFS = -DKERNEL -DRELEASE=$(RELEASE) "-DNAME=$(NAME)" |
DEFS = -DKERNEL -DRELEASE=$(RELEASE) "-DNAME=$(NAME)" -D__$(BITS)_BITS__ -D__$(ENDIANESS)__ |
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \ |
-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 |
-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 |
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) -imacros ../config.h \ |
-fno-builtin -Wall -Wmissing-prototypes -Werror \ |
/branches/dd/kernel/arch/sparc64/include/byteorder.h |
---|
File deleted |
/branches/dd/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/dd/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 |
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE) |
#ifdef context_set |
#undef context_set |
/branches/dd/kernel/arch/sparc64/Makefile.inc |
---|
40,7 → 40,8 |
LFLAGS += -no-check-sections -N |
DEFS += -D__64_BITS__ |
BITS = 64 |
ENDIANESS = BE |
ifeq ($(PROCESSOR),us) |
DEFS += -DUS |
/branches/dd/kernel/arch/sparc64/src/asm.S |
---|
277,7 → 277,7 |
*/ |
.global switch_to_userspace |
switch_to_userspace: |
save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp |
save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp |
flushw |
wrpr %g0, 0, %cleanwin ! avoid information leak |
/branches/dd/kernel/arch/ia64/include/byteorder.h |
---|
File deleted |
/branches/dd/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 = 0x01;;\n" |
"movl %0 = 0x1;;\n" |
"xchg8 %0 = %1, %0;;\n" |
: "=r" (v), "+m" (val->count) |
); |
65,6 → 65,13 |
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/dd/kernel/arch/ia64/include/mm/tlb.h |
---|
92,6 → 92,7 |
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/dd/kernel/arch/ia64/Makefile.inc |
---|
41,7 → 41,8 |
LFLAGS += -EL |
AFLAGS += -mconstant-gp |
DEFS += -D__64_BITS__ |
BITS = 64 |
ENDIANESS = LE |
ARCH_SOURCES = \ |
arch/$(KARCH)/src/start.S \ |
/branches/dd/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 |
HEAVYWEIGHT_HANDLER 0x5300 data_access_rights_fault |
HEAVYWEIGHT_HANDLER 0x5400 general_exception |
HEAVYWEIGHT_HANDLER 0x5500 disabled_fp_register |
HEAVYWEIGHT_HANDLER 0x5600 |
/branches/dd/kernel/arch/ia64/src/mm/tlb.c |
---|
710,6 → 710,37 |
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/dd/kernel/arch/arm32/include/byteorder.h |
---|
File deleted |
/branches/dd/kernel/arch/arm32/Makefile.inc |
---|
39,7 → 39,8 |
GCC_CFLAGS += -fno-zero-initialized-in-bss |
DEFS += -D__32_BITS__ |
BITS = 32 |
ENDIANESS = LE |
ARCH_SOURCES = \ |
arch/$(KARCH)/src/start.S \ |
/branches/dd/kernel/arch/ppc32/include/byteorder.h |
---|
File deleted |
/branches/dd/kernel/arch/ppc32/Makefile.inc |
---|
39,7 → 39,8 |
AFLAGS += -a32 |
LFLAGS += -no-check-sections -N |
DEFS += -D__32_BITS__ |
BITS = 32 |
ENDIANESS = BE |
ARCH_SOURCES = \ |
arch/$(KARCH)/src/context.S \ |
/branches/dd/kernel/arch/ppc32/src/ppc32.c |
---|
36,6 → 36,7 |
#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> |
117,31 → 118,6 |
/* 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(); |
} |
157,6 → 133,35 |
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/dd/kernel/arch/amd64/include/byteorder.h |
---|
File deleted |
/branches/dd/kernel/arch/amd64/Makefile.inc |
---|
41,7 → 41,8 |
ICC_CFLAGS += $(CMN1) |
SUNCC_CFLAGS += -m64 -xmodel=kernel |
DEFS += -D__64_BITS__ |
BITS = 64 |
ENDIANESS = LE |
## Accepted CPUs |
# |
/branches/dd/kernel/arch/mips32/include/byteorder.h |
---|
File deleted |
/branches/dd/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 100 |
#define REGISTER_SPACE 104 /* respect stack alignment */ |
#ifdef __ASM__ |
/branches/dd/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,17 → 35,15 |
#ifndef KERN_mips32_ELF_H_ |
#define KERN_mips32_ELF_H_ |
#include <byteorder.h> |
#define ELF_MACHINE EM_MIPS |
#define ELF_MACHINE EM_MIPS |
#ifdef ARCH_IS_BIG_ENDIAN |
# define ELF_DATA_ENCODING ELFDATA2MSB |
#ifdef __BE__ |
#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/dd/kernel/arch/mips32/Makefile.inc |
---|
36,7 → 36,7 |
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 |
DEFS += -D__32_BITS__ |
BITS = 32 |
## Accepted MACHINEs |
# |
43,15 → 43,18 |
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 |
GCC_CFLAGS += -DBIG_ENDIAN |
ENDIANESS = BE |
GCC_CFLAGS += -D__BE__ |
endif |
ifeq ($(MACHINE),msim) |
BFD_NAME = elf32-tradlittlemips |
ENDIANESS = LE |
GCC_CFLAGS += -mhard-float |
endif |
/branches/dd/kernel/arch/ia32/include/byteorder.h |
---|
File deleted |
/branches/dd/kernel/arch/ia32/Makefile.inc |
---|
35,7 → 35,8 |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686 |
DEFS += -D__32_BITS__ |
BITS = 32 |
ENDIANESS = LE |
CMN1 = -m32 |
GCC_CFLAGS += $(CMN1) |
/branches/dd/uspace/app/bdsh/input.c |
---|
147,8 → 147,10 |
{ |
char line[INPUT_MAX]; |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_EMPHASIS); |
printf("%s", usr->prompt); |
fflush(stdout); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
read_line(line, INPUT_MAX); |
/branches/dd/uspace/app/bdsh/cmds/modules/bdd/bdd.c |
---|
102,7 → 102,7 |
return CMD_FAILURE; |
} |
rc = block_cache_init(handle, BLOCK_SIZE, 2); |
rc = block_cache_init(handle, BLOCK_SIZE, 2, CACHE_MODE_WB); |
if (rc != EOK) { |
printf("Error: could not init block cache.\n"); |
return CMD_FAILURE; |
/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
50,48 → 50,9 |
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) |
108,20 → 69,7 |
/* 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); |
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; |
} |
ls_print(dp->d_name, buff); |
} |
free(buff); |
129,7 → 77,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. |
136,17 → 84,23 |
* |
* Now we just print basic DOS style lists */ |
static void ls_print_dir(const char *d) |
static void ls_print(const char *name, const char *pathname) |
{ |
printf("%-40s\t<dir>\n", d); |
struct stat s; |
int rc; |
return; |
} |
if (rc = stat(pathname, &s)) { |
/* 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); |
static void ls_print_file(const char *name, const char *pathname) |
{ |
printf("%-40s\t%llu\n", name, (long long) flen(pathname)); |
return; |
} |
166,7 → 120,7 |
int cmd_ls(char **argv) |
{ |
unsigned int argc; |
unsigned int scope; |
struct stat s; |
char *buff; |
DIR *dirp; |
184,19 → 138,17 |
else |
str_cpy(buff, PATH_MAX, argv[1]); |
scope = ls_scope(buff); |
switch (scope) { |
case LS_BOGUS: |
if (stat(buff, &s)) { |
cli_error(CL_ENOENT, buff); |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff, buff); |
break; |
case LS_DIR: |
} |
if (s.is_file) { |
ls_print(buff, buff); |
} else { |
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); |
204,7 → 156,6 |
} |
ls_scan_dir(buff, dirp); |
closedir(dirp); |
break; |
} |
free(buff); |
/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
9,8 → 9,7 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *, const char *); |
static void ls_print(const char *, const char *); |
#endif /* LS_H */ |
/branches/dd/uspace/app/bdsh/util.c |
---|
53,14 → 53,6 |
* 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"); |
67,13 → 59,11 |
cli_errno = CL_ENOMEM; |
return 1; |
} |
memset(usr->cwd, 0, sizeof(usr->cwd)); |
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1); |
if (NULL == usr->cwd) |
if (!getcwd(usr->cwd, PATH_MAX)) |
snprintf(usr->cwd, PATH_MAX, "(unknown)"); |
if (usr->prompt) |
free(usr->prompt); |
asprintf(&usr->prompt, "%s # ", usr->cwd); |
return 0; |
/branches/dd/uspace/app/bdsh/exec.c |
---|
112,7 → 112,9 |
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,6 → 127,12 |
return 1; |
} |
task_wait(tid); |
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/dd/uspace/app/init/init.c |
---|
41,11 → 41,13 |
#include <bool.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <sys/stat.h> |
#include <task.h> |
#include <malloc.h> |
#include <macros.h> |
#include <string.h> |
#include <devmap.h> |
#include <config.h> |
#include "init.h" |
static void info_print(void) |
55,31 → 57,31 |
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"; |
while (rc < 0) { |
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"); |
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; |
} |
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; |
87,27 → 89,39 |
static bool mount_devfs(void) |
{ |
int rc = -1; |
char null[MAX_DEVICE_NAME]; |
int null_id = devmap_null_create(); |
while (rc < 0) { |
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"); |
break; |
case ELIMIT: |
printf(NAME ": Unable to mount device filesystem\n"); |
return false; |
case ENOENT: |
printf(NAME ": Unknown filesystem type (devfs)\n"); |
return false; |
} |
if (null_id == -1) { |
printf(NAME ": Unable to create null device\n"); |
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; |
} |
114,7 → 128,11 |
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; |
124,10 → 142,45 |
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); |
134,9 → 187,9 |
printf(NAME ": Spawning getvc on %s\n", vc); |
dev_handle_t handle; |
devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING); |
rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING); |
if (handle >= 0) { |
if (rc == EOK) { |
argv[0] = "/app/getvc"; |
argv[1] = vc; |
argv[2] = app; |
144,10 → 197,25 |
if (!task_spawn("/app/getvc", argv)) |
printf(NAME ": Error spawning getvc on %s\n", vc); |
} else |
} else { |
printf(NAME ": Error waiting on %s\n", vc); |
} |
} |
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(); |
160,7 → 228,7 |
spawn("/srv/devfs"); |
if (!mount_devfs()) { |
return(NAME ": Exiting\n"); |
printf(NAME ": Exiting\n"); |
return -2; |
} |
169,7 → 237,19 |
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"); |
#endif |
#ifdef CONFIG_MOUNT_DATA |
mount_data(); |
#endif |
getvc("vc0", "/app/bdsh"); |
getvc("vc1", "/app/bdsh"); |
getvc("vc2", "/app/bdsh"); |
/branches/dd/uspace/app/init/Makefile |
---|
34,6 → 34,7 |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../.. |
LIBS = $(LIBC_PREFIX)/libc.a |
## Sources |
/branches/dd/uspace/app/tester/devmap/devmap1.def |
---|
File deleted |
/branches/dd/uspace/app/tester/devmap/devmap1.c |
---|
File deleted |
/branches/dd/uspace/app/tester/console/console1.c |
---|
46,65 → 46,78 |
[COLOR_WHITE] = "white" |
}; |
char * test_console1(bool quiet) |
char *test_console1(void) |
{ |
int i, j; |
printf("Style test: "); |
console_set_style(fphone(stdout), STYLE_NORMAL); |
printf("normal "); |
console_set_style(fphone(stdout), STYLE_EMPHASIS); |
printf("emphasized"); |
console_set_style(fphone(stdout), 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(fphone(stdout), i, COLOR_WHITE, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
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'); |
} |
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); |
putchar('\n'); |
} |
printf("Background color test:\n"); |
for (j = 0; j < 2; j++) { |
for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) { |
console_set_color(fphone(stdout), COLOR_WHITE, i, |
j ? CATTR_BRIGHT : 0); |
printf(" %s ", color_name[i]); |
for (i = 0; i < 255; i += 16) { |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8); |
putchar('X'); |
} |
fflush(stdout); |
console_set_color(fphone(stdout), 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(fphone(stdout), 0xffffff, i << 16); |
putchar('X'); |
} |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
for (i = 0; i < 255; i += 16) { |
console_set_rgb_color(fphone(stdout), 0xffffff, i << 8); |
putchar('X'); |
} |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
for (i = 0; i < 255; i += 16) { |
console_set_rgb_color(fphone(stdout), 0xffffff, i); |
putchar('X'); |
} |
console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); |
putchar('\n'); |
printf("[press a key]\n"); |
getchar(); |
return NULL; |
} |
/branches/dd/uspace/app/tester/stdio/stdio1.c |
---|
31,55 → 31,60 |
#include <errno.h> |
#include "../tester.h" |
#define BUF_SIZE 32 |
#define BUF_SIZE 32 |
static char buf[BUF_SIZE + 1]; |
char * test_stdio1(bool quiet) |
char *test_stdio1(void) |
{ |
FILE *f; |
FILE *file; |
char *file_name = "/readme"; |
size_t n; |
int c; |
printf("Open file '%s'\n", file_name); |
TPRINTF("Open file \"%s\"...", file_name); |
errno = 0; |
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"); |
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()..."); |
while (true) { |
c = fgetc(f); |
if (c == EOF) break; |
printf("'%c'", c); |
int c = fgetc(file); |
if (c == EOF) |
break; |
TPRINTF("."); |
} |
printf("[EOF]\n"); |
printf("Closing.\n"); |
if (fclose(f) != 0) |
return "Failed closing."; |
TPRINTF("[EOF]\n"); |
TPRINTF("Close..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
return NULL; |
} |
/branches/dd/uspace/app/tester/stdio/stdio2.c |
---|
31,39 → 31,53 |
#include <errno.h> |
#include "../tester.h" |
char * test_stdio2(bool quiet) |
char *test_stdio2(void) |
{ |
FILE *f; |
FILE *file; |
char *file_name = "/test"; |
size_t n; |
int c; |
printf("Open file '%s' for writing\n", file_name); |
TPRINTF("Open file \"%s\" for writing...", file_name); |
errno = 0; |
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"); |
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"); |
while (true) { |
c = fgetc(f); |
if (c == EOF) break; |
putchar(c); |
int c = fgetc(file); |
if (c == EOF) |
break; |
TPRINTF("%c", c); |
} |
if (fclose(f) != 0) |
return "Failed closing file."; |
TPRINTF("\nClose..."); |
if (fclose(file) != 0) { |
TPRINTF("errno = %d\n", errno); |
return "Failed closing file"; |
} else |
TPRINTF("OK\n"); |
return NULL; |
} |
/branches/dd/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,48 → 37,44 |
#include <unistd.h> |
#include <stdio.h> |
#include <string.h> |
#include "tester.h" |
int myservice = 0; |
int phones[MAX_PHONES]; |
int connections[MAX_CONNECTIONS]; |
ipc_callid_t callids[MAX_CONNECTIONS]; |
bool test_quiet; |
int test_argc; |
char **test_argv; |
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 "vfs/vfs1.def" |
#include "console/console1.def" |
#include "stdio/stdio1.def" |
#include "stdio/stdio2.def" |
{NULL, NULL, NULL} |
#include "mm/malloc1.def" |
{NULL, NULL, NULL, false} |
}; |
static bool run_test(test_t *test) |
{ |
printf("%s\t\t%s\n", test->name, test->desc); |
/* Execute the test */ |
char * ret = test->entry(false); |
char *ret = test->entry(); |
if (ret == NULL) { |
printf("Test passed\n\n"); |
printf("\nTest passed\n"); |
return true; |
} |
printf("%s\n\n", ret); |
printf("\n%s\n", ret); |
return false; |
} |
87,11 → 83,12 |
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 |
98,64 → 95,52 |
n++; |
} |
} |
printf("\nSafe tests completed, %u tests run, %u passed.\n\n", i + n, i); |
printf("\nCompleted, %u tests run, %u passed.\n", i + n, i); |
} |
static void list_tests(void) |
{ |
size_t len = 0; |
test_t *test; |
char c = 'a'; |
for (test = tests; test->name != NULL; test++) { |
if (str_length(test->name) > len) |
len = str_length(test->name); |
} |
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)")); |
for (test = tests; test->name != NULL; test++) |
printf("%-*s %s%s\n", len, test->name, test->desc, (test->safe ? "" : " (unsafe)")); |
printf("*\t\t\tRun all safe tests\n"); |
printf("%-*s Run all safe tests\n", len, "*"); |
} |
int main(int argc, char **argv) |
int main(int argc, char *argv[]) |
{ |
printf("Number of arguments: %d\n", argc); |
if (argv) { |
printf("Arguments:"); |
while (*argv) { |
printf(" '%s'", *argv++); |
} |
printf("\n"); |
if (argc < 2) { |
printf("Usage:\n\n"); |
printf("%s <test> [args ...]\n\n", argv[0]); |
list_tests(); |
return 0; |
} |
while (1) { |
char c; |
test_t *test; |
list_tests(); |
printf("> "); |
fflush(stdout); |
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"); |
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); |
} |
} |
return 0; |
printf("Unknown test \"%s\"\n", argv[1]); |
return -2; |
} |
/** @} |
/branches/dd/uspace/app/tester/thread/thread1.c |
---|
27,7 → 27,8 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#define THREADS 5 |
#define THREADS 20 |
#define DELAY 10 |
#include <atomic.h> |
#include <thread.h> |
42,40 → 43,38 |
static void threadtest(void *data) |
{ |
thread_detach(thread_get_id()); |
while (atomic_get(&finish)) { |
if (!sh_quiet) |
printf("%llu ", thread_get_id()); |
while (atomic_get(&finish)) |
usleep(100000); |
} |
atomic_inc(&threads_finished); |
} |
char * test_thread1(bool quiet) |
char *test_thread1(void) |
{ |
unsigned int i, total = 0; |
sh_quiet = quiet; |
unsigned int i; |
unsigned int total = 0; |
atomic_set(&finish, 1); |
atomic_set(&threads_finished, 0); |
for (i = 0; i < THREADS; i++) { |
TPRINTF("Creating threads"); |
for (i = 0; i < THREADS; i++) { |
if (thread_create(threadtest, NULL, "threadtest", NULL) < 0) { |
if (!quiet) |
printf("Could not create thread %d\n", i); |
TPRINTF("\nCould not create thread %u\n", i); |
break; |
} |
TPRINTF("."); |
total++; |
} |
if (!quiet) |
printf("Running threads for 10 seconds...\n"); |
sleep(10); |
TPRINTF("\nRunning threads for %u seconds...", DELAY); |
sleep(DELAY); |
TPRINTF("\n"); |
atomic_set(&finish, 0); |
while (atomic_get(&threads_finished) < total) { |
if (!quiet) |
printf("Threads left: %d\n", total - atomic_get(&threads_finished)); |
TPRINTF("Threads left: %u\n", total - atomic_get(&threads_finished)); |
sleep(1); |
} |
/branches/dd/uspace/app/tester/loop/loop1.c |
---|
30,12 → 30,11 |
#include <stdlib.h> |
#include "../tester.h" |
char *test_loop1(bool quiet) |
char *test_loop1(void) |
{ |
printf("Looping...\n"); |
while (1); |
printf("Survived endless loop?!!\n"); |
return NULL; |
TPRINTF("Looping..."); |
while (true); |
TPRINTF("\n"); |
return "Survived endless loop"; |
} |
/branches/dd/uspace/app/tester/mm/malloc1.def |
---|
0,0 → 1,6 |
{ |
"malloc1", |
"Memory allocator test", |
&test_malloc1, |
true |
}, |
/branches/dd/uspace/app/tester/mm/malloc1.c |
---|
0,0 → 1,651 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Tomas Bures |
* Copyright (c) 2009 Lubomir Bulej |
* 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 <stdlib.h> |
#include <malloc.h> |
#include "../tester.h" |
/* |
* The test consists of several phases which differ in the size of blocks |
* they allocate. The size of blocks is given as a range of minimum and |
* maximum allowed size. Each of the phases is divided into 3 subphases which |
* differ in the probability of free and alloc actions. Second subphase is |
* started when malloc returns 'out of memory' or when MAX_ALLOC is reached. |
* Third subphase is started after a given number of cycles. The third subphase |
* as well as the whole phase ends when all memory blocks are released. |
*/ |
/** |
* sizeof_array |
* @array array to determine the size of |
* |
* Returns the size of @array in array elements. |
*/ |
#define sizeof_array(array) \ |
(sizeof(array) / sizeof((array)[0])) |
#define MAX_ALLOC (16 * 1024 * 1024) |
/* |
* Subphase control structures: subphase termination conditions, |
* probabilities of individual actions, subphase control structure. |
*/ |
typedef struct { |
unsigned int max_cycles; |
unsigned int no_memory; |
unsigned int no_allocated; |
} sp_term_cond_s; |
typedef struct { |
unsigned int alloc; |
unsigned int free; |
} sp_action_prob_s; |
typedef struct { |
char *name; |
sp_term_cond_s cond; |
sp_action_prob_s prob; |
} subphase_s; |
/* |
* Phase control structures: The minimum and maximum block size that |
* can be allocated during the phase execution, phase control structure. |
*/ |
typedef struct { |
size_t min_block_size; |
size_t max_block_size; |
} ph_alloc_size_s; |
typedef struct { |
char *name; |
ph_alloc_size_s alloc; |
subphase_s *subphases; |
} phase_s; |
/* |
* Subphases are defined separately here. This is for two reasons: |
* 1) data are not duplicated, 2) we don't have to state beforehand |
* how many subphases a phase contains. |
*/ |
static subphase_s subphases_32B[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 200, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 90, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 200, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 10, |
.free = 100 |
} |
} |
}; |
static subphase_s subphases_128K[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 70, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 30, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 30, |
.free = 100 |
} |
} |
}; |
static subphase_s subphases_default[] = { |
{ |
.name = "Allocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 1, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 90, |
.free = 100 |
} |
}, |
{ |
.name = "Alloc/Dealloc", |
.cond = { |
.max_cycles = 200, |
.no_memory = 0, |
.no_allocated = 0, |
}, |
.prob = { |
.alloc = 50, |
.free = 100 |
} |
}, |
{ |
.name = "Deallocation", |
.cond = { |
.max_cycles = 0, |
.no_memory = 0, |
.no_allocated = 1, |
}, |
.prob = { |
.alloc = 10, |
.free = 100 |
} |
} |
}; |
/* |
* Phase definitions. |
*/ |
static phase_s phases[] = { |
{ |
.name = "32 B memory blocks", |
.alloc = { |
.min_block_size = 32, |
.max_block_size = 32 |
}, |
.subphases = subphases_32B |
}, |
{ |
.name = "128 KB memory blocks", |
.alloc = { |
.min_block_size = 128 * 1024, |
.max_block_size = 128 * 1024 |
}, |
.subphases = subphases_128K |
}, |
{ |
.name = "2500 B memory blocks", |
.alloc = { |
.min_block_size = 2500, |
.max_block_size = 2500 |
}, |
.subphases = subphases_default |
}, |
{ |
.name = "1 B .. 250000 B memory blocks", |
.alloc = { |
.min_block_size = 1, |
.max_block_size = 250000 |
}, |
.subphases = subphases_default |
} |
}; |
/* |
* Global error flag. The flag is set if an error |
* is encountered (overlapping blocks, inconsistent |
* block data, etc.) |
*/ |
static bool error_flag = false; |
/* |
* Memory accounting: the amount of allocated memory and the |
* number and list of allocated blocks. |
*/ |
static size_t mem_allocated; |
static size_t mem_blocks_count; |
static LIST_INITIALIZE(mem_blocks); |
typedef struct { |
/* Address of the start of the block */ |
void *addr; |
/* Size of the memory block */ |
size_t size; |
/* link to other blocks */ |
link_t link; |
} mem_block_s; |
typedef mem_block_s *mem_block_t; |
/** init_mem |
* |
* Initializes the memory accounting structures. |
* |
*/ |
static void init_mem(void) |
{ |
mem_allocated = 0; |
mem_blocks_count = 0; |
} |
static bool overlap_match(link_t *entry, void *addr, size_t size) |
{ |
mem_block_t mblk = list_get_instance(entry, mem_block_s, link); |
/* Entry block control structure <mbeg, mend) */ |
uint8_t *mbeg = (uint8_t *) mblk; |
uint8_t *mend = (uint8_t *) mblk + sizeof(mem_block_s); |
/* Entry block memory <bbeg, bend) */ |
uint8_t *bbeg = (uint8_t *) mblk->addr; |
uint8_t *bend = (uint8_t *) mblk->addr + mblk->size; |
/* Data block <dbeg, dend) */ |
uint8_t *dbeg = (uint8_t *) addr; |
uint8_t *dend = (uint8_t *) addr + size; |
/* Check for overlaps */ |
if (((mbeg >= dbeg) && (mbeg < dend)) || |
((mend > dbeg) && (mend <= dend)) || |
((bbeg >= dbeg) && (bbeg < dend)) || |
((bend > dbeg) && (bend <= dend))) |
return true; |
return false; |
} |
/** test_overlap |
* |
* Test whether a block starting at @addr overlaps with another, previously |
* allocated memory block or its control structure. |
* |
* @param addr Initial address of the block |
* @param size Size of the block |
* |
* @return false if the block does not overlap. |
* |
*/ |
static int test_overlap(void *addr, size_t size) |
{ |
link_t *entry; |
bool fnd = false; |
for (entry = mem_blocks.next; entry != &mem_blocks; entry = entry->next) { |
if (overlap_match(entry, addr, size)) { |
fnd = true; |
break; |
} |
} |
return fnd; |
} |
/** checked_malloc |
* |
* Allocate @size bytes of memory and check whether the chunk comes |
* from the non-mapped memory region and whether the chunk overlaps |
* with other, previously allocated, chunks. |
* |
* @param size Amount of memory to allocate |
* |
* @return NULL if the allocation failed. Sets the global error_flag to |
* true if the allocation succeeded but is illegal. |
* |
*/ |
static void *checked_malloc(size_t size) |
{ |
void *data; |
/* Allocate the chunk of memory */ |
data = malloc(size); |
if (data == NULL) |
return NULL; |
/* Check for overlaps with other chunks */ |
if (test_overlap(data, size)) { |
TPRINTF("\nError: Allocated block overlaps with another " |
"previously allocated block.\n"); |
error_flag = true; |
} |
return data; |
} |
/** alloc_block |
* |
* Allocate a block of memory of @size bytes and add record about it into |
* the mem_blocks list. Return a pointer to the block holder structure or |
* NULL if the allocation failed. |
* |
* If the allocation is illegal (e.g. the memory does not come from the |
* right region or some of the allocated blocks overlap with others), |
* set the global error_flag. |
* |
* @param size Size of the memory block |
* |
*/ |
static mem_block_t alloc_block(size_t size) |
{ |
/* Check for allocation limit */ |
if (mem_allocated >= MAX_ALLOC) |
return NULL; |
/* Allocate the block holder */ |
mem_block_t block = (mem_block_t) checked_malloc(sizeof(mem_block_s)); |
if (block == NULL) |
return NULL; |
link_initialize(&block->link); |
/* Allocate the block memory */ |
block->addr = checked_malloc(size); |
if (block->addr == NULL) { |
free(block); |
return NULL; |
} |
block->size = size; |
/* Register the allocated block */ |
list_append(&block->link, &mem_blocks); |
mem_allocated += size + sizeof(mem_block_s); |
mem_blocks_count++; |
return block; |
} |
/** free_block |
* |
* Free the block of memory and the block control structure allocated by |
* alloc_block. Set the global error_flag if an error occurs. |
* |
* @param block Block control structure |
* |
*/ |
static void free_block(mem_block_t block) |
{ |
/* Unregister the block */ |
list_remove(&block->link); |
mem_allocated -= block->size + sizeof(mem_block_s); |
mem_blocks_count--; |
/* Free the memory */ |
free(block->addr); |
free(block); |
} |
/** expected_value |
* |
* Compute the expected value of a byte located at @pos in memory |
* block described by @blk. |
* |
* @param blk Memory block control structure |
* @param pos Position in the memory block data area |
* |
*/ |
static inline uint8_t expected_value(mem_block_t blk, uint8_t *pos) |
{ |
return ((unsigned long) blk ^ (unsigned long) pos) & 0xff; |
} |
/** fill_block |
* |
* Fill the memory block controlled by @blk with data. |
* |
* @param blk Memory block control structure |
* |
*/ |
static void fill_block(mem_block_t blk) |
{ |
uint8_t *pos; |
uint8_t *end; |
for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) |
*pos = expected_value(blk, pos); |
} |
/** check_block |
* |
* Check whether the block @blk contains the data it was filled with. |
* Set global error_flag if an error occurs. |
* |
* @param blk Memory block control structure |
* |
*/ |
static void check_block(mem_block_t blk) |
{ |
uint8_t *pos; |
uint8_t *end; |
for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) { |
if (*pos != expected_value (blk, pos)) { |
TPRINTF("\nError: Corrupted content of a data block.\n"); |
error_flag = true; |
return; |
} |
} |
} |
static link_t *list_get_nth(link_t *list, unsigned int i) |
{ |
unsigned int cnt = 0; |
link_t *entry; |
for (entry = list->next; entry != list; entry = entry->next) { |
if (cnt == i) |
return entry; |
cnt++; |
} |
return NULL; |
} |
/** get_random_block |
* |
* Select a random memory block from the list of allocated blocks. |
* |
* @return Block control structure or NULL if the list is empty. |
* |
*/ |
static mem_block_t get_random_block(void) |
{ |
if (mem_blocks_count == 0) |
return NULL; |
unsigned int blkidx = rand() % mem_blocks_count; |
link_t *entry = list_get_nth(&mem_blocks, blkidx); |
if (entry == NULL) { |
TPRINTF("\nError: Corrupted list of allocated memory blocks.\n"); |
error_flag = true; |
} |
return list_get_instance(entry, mem_block_s, link); |
} |
#define RETURN_IF_ERROR \ |
{ \ |
if (error_flag) \ |
return; \ |
} |
static void do_subphase(phase_s *phase, subphase_s *subphase) |
{ |
unsigned int cycles; |
for (cycles = 0; /* always */; cycles++) { |
if (subphase->cond.max_cycles && |
cycles >= subphase->cond.max_cycles) { |
/* |
* We have performed the required number of |
* cycles. End the current subphase. |
*/ |
break; |
} |
/* |
* Decide whether we alloc or free memory in this step. |
*/ |
unsigned int rnd = rand() % 100; |
if (rnd < subphase->prob.alloc) { |
/* Compute a random number lying in interval <min_block_size, max_block_size> */ |
int alloc = phase->alloc.min_block_size + |
(rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1)); |
mem_block_t blk = alloc_block(alloc); |
RETURN_IF_ERROR; |
if (blk == NULL) { |
TPRINTF("F(A)"); |
if (subphase->cond.no_memory) { |
/* We filled the memory. Proceed to next subphase */ |
break; |
} |
} else { |
TPRINTF("A"); |
fill_block(blk); |
} |
} else if (rnd < subphase->prob.free) { |
mem_block_t blk = get_random_block(); |
if (blk == NULL) { |
TPRINTF("F(R)"); |
if (subphase->cond.no_allocated) { |
/* We free all the memory. Proceed to next subphase. */ |
break; |
} |
} else { |
TPRINTF("R"); |
check_block(blk); |
RETURN_IF_ERROR; |
free_block(blk); |
RETURN_IF_ERROR; |
} |
} |
} |
TPRINTF("\n.. finished.\n"); |
} |
static void do_phase(phase_s *phase) |
{ |
unsigned int subno; |
for (subno = 0; subno < 3; subno++) { |
subphase_s *subphase = & phase->subphases [subno]; |
TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name); |
do_subphase(phase, subphase); |
RETURN_IF_ERROR; |
} |
} |
char *test_malloc1(void) |
{ |
init_mem(); |
unsigned int phaseno; |
for (phaseno = 0; phaseno < sizeof_array(phases); phaseno++) { |
phase_s *phase = &phases[phaseno]; |
TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name); |
do_phase(phase); |
if (error_flag) |
break; |
TPRINTF("Phase finished.\n"); |
} |
if (error_flag) |
return "Test failed"; |
return NULL; |
} |
/branches/dd/uspace/app/tester/fault/fault1.c |
---|
29,7 → 29,7 |
#include "../tester.h" |
char * test_fault1(bool quiet) |
char *test_fault1(void) |
{ |
((int *)(0))[1] = 0; |
/branches/dd/uspace/app/tester/fault/fault2.c |
---|
29,7 → 29,7 |
#include "../tester.h" |
char * test_fault2(bool quiet) |
char *test_fault2(void) |
{ |
volatile long long var; |
volatile int var1; |
/branches/dd/uspace/app/tester/ipc/send_sync.def |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/answer.def |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/send_async.def |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/answer.c |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/hangup.def |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/send_async.c |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/send_sync.c |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/hangup.c |
---|
File deleted |
/branches/dd/uspace/app/tester/ipc/ping_pong.c |
---|
37,20 → 37,23 |
#define DURATION_SECS 10 |
#define COUNT_GRANULARITY 100 |
char *test_ping_pong(bool quiet) |
char *test_ping_pong(void) |
{ |
printf("Pinging ns server for %d seconds...\n", DURATION_SECS); |
TPRINTF("Pinging ns server for %d seconds...", DURATION_SECS); |
struct timeval start; |
if (gettimeofday(&start, NULL) != 0) |
return "Failed getting the time."; |
if (gettimeofday(&start, NULL) != 0) { |
TPRINTF("\n"); |
return "Failed getting the time"; |
} |
uint64_t count = 0; |
while (true) { |
struct timeval now; |
if (gettimeofday(&now, NULL) != 0) |
return "Failed getting the time."; |
if (gettimeofday(&now, NULL) != 0) { |
TPRINTF("\n"); |
return "Failed getting the time"; |
} |
if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L) |
break; |
59,14 → 62,16 |
for (i = 0; i < COUNT_GRANULARITY; i++) { |
int retval = async_req_0_0(PHONE_NS, NS_PING); |
if (retval != EOK) |
return "Failed to send ping message."; |
if (retval != EOK) { |
TPRINTF("\n"); |
return "Failed to send ping message"; |
} |
} |
count += COUNT_GRANULARITY; |
} |
printf("Completed %lu round trips in %u seconds, %lu RT/s.\n", |
TPRINTF("OK\nCompleted %llu round trips in %u seconds, %llu rt/s.\n", |
count, DURATION_SECS, count / DURATION_SECS); |
return NULL; |
/branches/dd/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) |
{ |
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); |
unsigned int i; |
TPRINTF("Connected phone %#x accepting\n", icall->in_phone_hash); |
ipc_answer_0(iid, EOK); |
for (i = 0; i < 1024; i++) |
for (i = 0; i < MAX_CONNECTIONS; i++) { |
if (!connections[i]) { |
connections[i] = phonehash; |
connections[i] = icall->in_phone_hash; |
break; |
} |
} |
while (1) { |
callid = async_get_call(&call); |
while (true) { |
ipc_call_t call; |
ipc_callid_t callid = async_get_call(&call); |
int retval; |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_PHONE_HUNGUP: |
printf("Phone (%P) hung up.\n", phonehash); |
TPRINTF("Phone %#x hung up\n", icall->in_phone_hash); |
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: |
printf("Received message from %P: %X\n", phonehash, |
callid); |
for (i = 0; i < 1024; i++) |
if (!callids[i]) { |
callids[i] = callid; |
break; |
} |
continue; |
TPRINTF("Received unknown message from %#x: %#x\n", |
icall->in_phone_hash, callid); |
ipc_answer_0(callid, ENOENT); |
break; |
} |
ipc_answer_0(callid, retval); |
} |
} |
char * test_register(bool quiet) |
char *test_register(void) |
{ |
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/dd/uspace/app/tester/ipc/connect.c |
---|
28,32 → 28,46 |
#include <stdio.h> |
#include <unistd.h> |
#include <atomic.h> |
#include "../tester.h" |
char * test_connect(bool quiet) |
static atomic_t finish; |
static void callback(void *priv, int retval, ipc_call_t *data) |
{ |
char c; |
int svc; |
int phid; |
atomic_set(&finish, 1); |
} |
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'); |
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"; |
} |
svc = IPC_TEST_START + c - '0'; |
if (svc == myservice) |
return "Currently cannot connect to myself, update test"; |
printf("Sending synchronous message...\n"); |
int retval = ipc_call_sync_0_0(phone, IPC_TEST_METHOD); |
TPRINTF("Received response to synchronous 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("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"); |
TPRINTF("Hanging up..."); |
retval = ipc_hangup(phone); |
if (retval == 0) { |
TPRINTF("OK\n"); |
} else { |
TPRINTF("\n"); |
return "ipc_hangup() failed"; |
} |
return NULL; |
} |
/branches/dd/uspace/app/tester/print/print2.c |
---|
0,0 → 1,52 |
/* |
* Copyright (c) 2005 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 "../tester.h" |
char *test_print2(void) |
{ |
TPRINTF("Testing printf(\"%%c %%3.2c %%-3.2c %%2.3c %%-2.3c\", 'a', 'b', 'c', 'd', 'e'):\n"); |
TPRINTF("Expected output: [a] [ b] [c ] [ d] [e ]\n"); |
TPRINTF("Real output: [%c] [%3.2c] [%-3.2c] [%2.3c] [%-2.3c]\n\n", 'a', 'b', 'c', 'd', 'e'); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", 1, 2, 3, 4, 5):\n"); |
TPRINTF("Expected output: [1] [ 02] [03 ] [004] [005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", 1, 2, 3, 4, 5); |
TPRINTF("Testing printf(\"%%d %%3.2d %%-3.2d %%2.3d %%-2.3d\", -1, -2, -3, -4, -5):\n"); |
TPRINTF("Expected output: [-1] [-02] [-03] [-004] [-005]\n"); |
TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); |
TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); |
TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); |
TPRINTF("Real output: [%#x] [%#5.3x] [%#-5.3x] [%#3.5x] [%#-3.5x]\n\n", 17, 18, 19, 20, 21); |
return NULL; |
} |
/branches/dd/uspace/app/tester/print/print3.c |
---|
0,0 → 1,62 |
/* |
* Copyright (c) 2005 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 <macros.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char *test_print3(void) |
{ |
char buffer[BUFFER_SIZE]; |
int retval; |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=30 buffer=\"Short text without parameters.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very very very long text without parameters.\"):\n"); |
TPRINTF("Expected result: retval=44 buffer=\"Very very very long text withou\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Very very very long text without parameters."); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Short %%s.\", \"text\"):\n"); |
TPRINTF("Expected result: retval=11 buffer=\"Short text.\"\n"); |
retval = snprintf(buffer, BUFFER_SIZE, "Short %s.", "text"); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
TPRINTF("Testing snprintf(buffer, " STRING(BUFFER_SIZE) ", \"Very long %%s. This text's length is more than %%d. We are interested in the result.\", \"text\", " STRING(BUFFER_SIZE) "):\n"); |
TPRINTF("Expected result: retval=84 buffer=\"Very long text. This text's len\"\n"); |
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); |
TPRINTF("Real result: retval=%d buffer=\"%s\"\n\n", retval, buffer); |
return NULL; |
} |
/branches/dd/uspace/app/tester/print/print4.c |
---|
30,63 → 30,54 |
#include <unistd.h> |
#include "../tester.h" |
#define PRIx8 "x" |
char *test_print4(bool quiet) |
char *test_print4(void) |
{ |
if (!quiet) { |
printf("ASCII printable characters (32 - 127) using printf(\"%%c\") and printf(\"%%lc\"):\n"); |
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); |
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"); |
} |
uint8_t index; |
for (index = 0; index < 32; index++) |
TPRINTF("%c", (char) ((group << 5) + index)); |
printf("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
TPRINTF(" "); |
for (index = 0; index < 32; index++) |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
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"); |
} |
TPRINTF("\n"); |
} |
TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); |
for (group = 4; group < 8; group++) { |
TPRINTF("%#x: ", group << 5); |
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", "Սկսեց հրատարակվել Երուսաղեմի հայկական"); |
uint8_t index; |
for (index = 0; index < 32; index++) |
TPRINTF("%lc", (wchar_t) ((group << 5) + index)); |
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'); |
TPRINTF("\n"); |
} |
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/dd/uspace/app/tester/print/print1.def |
---|
1,6 → 1,6 |
{ |
"print1", |
"Printf test", |
"String printf test", |
&test_print1, |
true |
}, |
/branches/dd/uspace/app/tester/print/print2.def |
---|
0,0 → 1,6 |
{ |
"print2", |
"Numeric printf test", |
&test_print2, |
true |
}, |
/branches/dd/uspace/app/tester/print/print3.def |
---|
0,0 → 1,6 |
{ |
"print3", |
"Buffered printf test", |
&test_print3, |
true |
}, |
/branches/dd/uspace/app/tester/print/print1.c |
---|
30,44 → 30,27 |
#include <unistd.h> |
#include "../tester.h" |
#define BUFFER_SIZE 32 |
char * test_print1(bool quiet) |
char *test_print1(void) |
{ |
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(\"%%*.*s\", 5, 3, \"text\"):\n"); |
TPRINTF("Expected output: \" tex\"\n"); |
TPRINTF("Real output: \"%*.*s\"\n\n", 5, 3, "text"); |
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/dd/uspace/app/tester/tester.h |
---|
39,43 → 39,45 |
#include <bool.h> |
#include <ipc/ipc.h> |
#define IPC_TEST_START 10000 |
#define MAX_PHONES 20 |
#define MAX_CONNECTIONS 50 |
#define TEST_SKIPPED "Test Skipped" |
#define IPC_TEST_SERVICE 10240 |
#define IPC_TEST_METHOD 2000 |
extern int myservice; |
extern int phones[MAX_PHONES]; |
extern int connections[MAX_CONNECTIONS]; |
extern ipc_callid_t callids[MAX_CONNECTIONS]; |
extern bool test_quiet; |
extern int test_argc; |
extern char **test_argv; |
typedef char * (* test_entry_t)(bool); |
#define TPRINTF(format, ...) \ |
{ \ |
if (!test_quiet) { \ |
fprintf(stderr, format, ##__VA_ARGS__); \ |
} \ |
} |
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(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 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 test_t tests[]; |
/branches/dd/uspace/app/tester/Makefile |
---|
45,22 → 45,20 |
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 \ |
devmap/devmap1.c \ |
console/console1.c \ |
stdio/stdio1.c \ |
stdio/stdio2.c \ |
vfs/vfs1.c |
mm/malloc1.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
/branches/dd/uspace/app/tester/vfs/vfs1.c |
---|
34,109 → 34,118 |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include "../tester.h" |
char text[] = "O xein', angellein Lakedaimoniois hoti teide " |
"keimetha tois keinon rhemasi peithomenoi."; |
#define FS_TYPE "tmpfs" |
#define MOUNT_POINT "/tmp" |
#define OPTIONS "" |
#define FLAGS 0 |
char *test_vfs1(bool quiet) |
#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) |
{ |
int rc; |
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; |
} |
rc = mount("tmpfs", "/", "nulldev0", "", 0); |
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); |
switch (rc) { |
case EOK: |
if (!quiet) |
printf("mounted tmpfs on /\n"); |
TPRINTF("Mounted /dev/%s as %s on %s\n", null, FS_TYPE, MOUNT_POINT); |
break; |
case EBUSY: |
if (!quiet) |
printf("(INFO) something is already mounted on /\n"); |
TPRINTF("(INFO) Filesystem already mounted on %s\n", MOUNT_POINT); |
break; |
default: |
if (!quiet) |
printf("(INFO) IPC returned errno %d\n", rc); |
return "mount() failed."; |
TPRINTF("(ERR) IPC returned errno %d (is tmpfs loaded?)\n", rc); |
return "mount() failed"; |
} |
if (mkdir("/mydir", 0) != 0) |
return "mkdir() failed.\n"; |
if (!quiet) |
printf("created directory /mydir\n"); |
int fd0 = open("/mydir/myfile", O_CREAT); |
if (mkdir(TEST_DIRECTORY, 0) != 0) |
return "mkdir() failed"; |
TPRINTF("Created directory %s\n", TEST_DIRECTORY); |
int fd0 = open(TEST_FILE, O_CREAT); |
if (fd0 < 0) |
return "open() failed.\n"; |
if (!quiet) |
printf("created file /mydir/myfile, fd=%d\n", fd0); |
ssize_t cnt; |
return "open() failed"; |
TPRINTF("Created file %s (fd=%d)\n", TEST_FILE, fd0); |
size_t size = sizeof(text); |
cnt = write(fd0, text, size); |
ssize_t cnt = write(fd0, text, size); |
if (cnt < 0) |
return "write() failed.\n"; |
if (!quiet) |
printf("written %d bytes, fd=%d\n", cnt, fd0); |
return "write() failed"; |
TPRINTF("Written %d bytes\n", cnt); |
if (lseek(fd0, 0, SEEK_SET) != 0) |
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)))) { |
return "lseek() failed"; |
TPRINTF("Sought to position 0\n"); |
char buf[BUF_SIZE]; |
while ((cnt = read(fd0, buf, BUF_SIZE))) { |
if (cnt < 0) |
return "read() failed.\n"; |
if (!quiet) |
printf("read %d bytes: \"%.*s\", fd=%d\n", cnt, cnt, |
buf, fd0); |
return "read() failed"; |
TPRINTF("Read %d bytes: \".*s\"\n", cnt, cnt, buf); |
} |
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"; |
if (!quiet) |
printf("unlinked file /mydir/yourfile\n"); |
if (rmdir("/mydir")) |
return "rmdir() failed.\n"; |
if (!quiet) |
printf("removed directory /mydir\n"); |
char *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); |
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; |
return NULL; |
} |
/branches/dd/uspace/app/getvc/getvc.c |
---|
73,6 → 73,9 |
int main(int argc, char *argv[]) |
{ |
task_exit_t texit; |
int retval; |
if (argc < 3) { |
usage(); |
return -1; |
83,6 → 86,12 |
stdin = fopen(argv[1], "r"); |
stdout = fopen(argv[1], "w"); |
stderr = fopen(argv[1], "w"); |
/* |
* FIXME: fopen() should actually detect that we are opening a console |
* and it should set line-buffering mode automatically. |
*/ |
setvbuf(stdout, NULL, _IOLBF, BUFSIZ); |
if ((stdin == NULL) |
|| (stdout == NULL) |
91,7 → 100,7 |
version_print(argv[1]); |
task_id_t id = spawn(argv[2]); |
task_wait(id); |
task_wait(id, &texit, &retval); |
return 0; |
} |
/branches/dd/uspace/app/tetris/scores.c |
---|
196,5 → 196,38 |
} |
} |
int loadscores(void) |
{ |
FILE *f; |
size_t cnt; |
int rc; |
f = fopen("/data/tetris.sco", "rb"); |
if (f == NULL) |
return ENOENT; |
cnt = fread(scores, sizeof(struct highscore), NUMSPOTS, f); |
rc = fclose(f); |
if (cnt != NUMSPOTS || rc != 0) |
return EIO; |
return EOK; |
} |
void savescores(void) |
{ |
FILE *f; |
size_t cnt; |
int rc; |
f = fopen("/data/tetris.sco", "wb"); |
cnt = fwrite(scores, sizeof(struct highscore), NUMSPOTS, f); |
rc = fclose(f); |
if (cnt != NUMSPOTS || rc != 0) |
printf("Error saving score table\n"); |
} |
/** @} |
*/ |
/branches/dd/uspace/app/tetris/screen.c |
---|
62,6 → 62,8 |
static int curscore; |
static int isset; /* true => terminal is in game mode */ |
static int use_color; /* true => use colors */ |
static const struct shape *lastshape; |
77,11 → 79,14 |
static void start_standout(uint32_t color) |
{ |
console_set_rgb_color(fphone(stdout), 0xf0f0f0, color); |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0xf0f0f0, |
use_color ? color : 0x000000); |
} |
static void resume_normal(void) |
{ |
fflush(stdout); |
console_set_rgb_color(fphone(stdout), 0, 0xf0f0f0); |
} |
114,6 → 119,7 |
void moveto(int r, int c) |
{ |
fflush(stdout); |
console_goto(fphone(stdout), c, r); |
} |
124,6 → 130,18 |
return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row); |
} |
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. |
*/ |
138,6 → 156,8 |
Rows = ws.ws_row; |
Cols = ws.ws_col; |
} |
use_color = get_display_color_sup(); |
if ((Rows < MINROWS) || (Cols < MINCOLS)) { |
char smallscr[55]; |
/branches/dd/uspace/app/tetris/scores.h |
---|
64,6 → 64,8 |
extern void showscores(int); |
extern void initscores(void); |
extern void insertscore(int score, int level); |
extern int loadscores(void); |
extern void savescores(void); |
/** @} |
*/ |
/branches/dd/uspace/app/tetris/tetris.c |
---|
49,6 → 49,7 |
#include <sys/time.h> |
#include <sys/types.h> |
#include <err.h> |
#include <errno.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
206,6 → 207,7 |
printf("off"); |
break; |
case 'h': |
loadscores(); |
showscores(firstgame); |
tetris_menu_draw(*level); |
break; |
297,7 → 299,9 |
key_write[4], key_write[5]); |
scr_init(); |
initscores(); |
if (loadscores() != EOK) |
initscores(); |
while (tetris_menu(&level)) { |
fallrate = 1000000 / level; |
415,7 → 419,9 |
} |
scr_clear(); |
loadscores(); |
insertscore(score, level); |
savescores(); |
score = 0; |
} |
/branches/dd/uspace/app/trace/trace.c |
---|
43,7 → 43,11 |
#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> |
64,22 → 68,31 |
int next_thread_id; |
ipc_call_t thread_ipc_req[THBUF_SIZE]; |
int phoneid; |
int abort_trace; |
bool abort_trace; |
uintptr_t thash; |
volatile int paused; |
static bool paused; |
static fibril_condvar_t state_cv; |
static fibril_mutex_t state_lock; |
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) |
{ |
94,6 → 107,19 |
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; |
315,7 → 341,7 |
ipcp_call_sync(phoneidx, &question, &reply); |
} |
static void sc_ipc_call_sync_slow(sysarg_t *sc_args) |
static void sc_ipc_call_sync_slow_b(unsigned thread_id, sysarg_t *sc_args) |
{ |
ipc_call_t question, reply; |
int rc; |
322,15 → 348,27 |
memset(&question, 0, sizeof(question)); |
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 question, reply; |
int rc; |
memset(&reply, 0, sizeof(reply)); |
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], &question, &reply); |
ipcp_call_sync(sc_args[0], &thread_ipc_req[thread_id], &reply); |
} |
static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc) |
375,6 → 413,14 |
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(); |
} |
415,7 → 461,7 |
sc_ipc_call_sync_fast(sc_args); |
break; |
case SYS_IPC_CALL_SYNC_SLOW: |
sc_ipc_call_sync_slow(sc_args); |
sc_ipc_call_sync_slow_e(thread_id, sc_args); |
break; |
case SYS_IPC_WAIT: |
sc_ipc_wait(sc_args, sc_rc); |
446,20 → 492,26 |
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("Press R to resume (and be patient).\n"); |
while (paused) { |
usleep(1000000); |
fibril_yield(); |
printf("."); |
} |
printf("Resumed\n"); |
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); |
} |
fibril_mutex_unlock(&state_lock); |
/* Run thread until an event occurs */ |
rc = udebug_go(phoneid, thread_hash, |
481,6 → 533,9 |
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); |
487,7 → 542,10 |
break; |
case UDEBUG_EVENT_THREAD_E: |
printf("Thread 0x%lx exited.\n", val0); |
abort_trace = 1; |
fibril_mutex_lock(&state_lock); |
abort_trace = true; |
fibril_condvar_broadcast(&state_cv); |
fibril_mutex_unlock(&state_lock); |
break; |
default: |
printf("Unknown event type %d.\n", ev_type); |
540,6 → 598,33 |
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) |
555,11 → 640,32 |
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(); |
575,29 → 681,55 |
return; |
} |
abort_trace = 0; |
abort_trace = false; |
for (i = 0; i < n_threads; i++) { |
thread_trace_start(thread_hash_buf[i]); |
} |
while(1) { |
c = getchar(); |
if (c == 'q') break; |
if (c == 'p') { |
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: |
printf("Pause...\n"); |
paused = 1; |
rc = udebug_stop(phoneid, thash); |
printf("stop -> %d\n", rc); |
} |
if (c == 'r') { |
paused = 0; |
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("Resume...\n"); |
break; |
} |
} |
printf("\nTerminate debugging session...\n"); |
abort_trace = 1; |
abort_trace = true; |
udebug_end(phoneid); |
ipc_hangup(phoneid); |
629,37 → 761,53 |
}; |
next_thread_id = 1; |
paused = 0; |
paused = false; |
cev_valid = false; |
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_READ, o); |
proto_add_oper(p, VFS_IN_READ, o); |
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def); |
proto_add_oper(p, VFS_WRITE, o); |
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); |
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_TRUNCATE, o); |
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); |
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MOUNT, o); |
proto_add_oper(p, VFS_IN_MOUNT, o); |
/* o = oper_new("unmount", 0, arg_def); |
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); |
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); |
o = oper_new("mkdir", 1, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_MKDIR, o); |
proto_add_oper(p, VFS_IN_MKDIR, o); |
o = oper_new("unlink", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_UNLINK, o); |
proto_add_oper(p, VFS_IN_UNLINK, o); |
o = oper_new("rename", 0, arg_def, V_ERRNO, 0, resp_def); |
proto_add_oper(p, VFS_RENAME, o); |
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_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); |
752,6 → 900,7 |
--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(); |
789,6 → 938,7 |
while (*cp) printf("'%s'\n", *cp++); |
} |
task_ldr = preload_task(*argv, argv, &task_id); |
task_wait_for = true; |
return 0; |
} |
796,6 → 946,8 |
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"); |
815,12 → 967,29 |
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/dd/uspace/lib/libfs/libfs.c |
---|
43,6 → 43,7 |
#include <assert.h> |
#include <dirent.h> |
#include <mem.h> |
#include <sys/stat.h> |
/** Register file system server. |
* |
69,7 → 70,7 |
* out-of-order, when it knows that the operation succeeded or failed. |
*/ |
ipc_call_t answer; |
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer); |
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); |
/* |
* Send our VFS info structure to VFS. |
104,7 → 105,7 |
} |
/* |
* Pick up the answer for the request to the VFS_REQUEST call. |
* Pick up the answer for the request to the VFS_IN_REQUEST call. |
*/ |
async_wait_for(req, NULL); |
reg->fs_handle = (int) IPC_GET_ARG1(answer); |
186,7 → 187,7 |
} |
ipc_call_t answer; |
aid_t msg = async_send_1(mountee_phone, VFS_MOUNTED, mr_dev_handle, |
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); |
213,8 → 214,8 |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_LOOKUP request. |
* @param request VFS_LOOKUP request data itself. |
* @param rid Request ID of the VFS_OUT_LOOKUP request. |
* @param request VFS_OUT_LOOKUP request data itself. |
* |
*/ |
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
237,7 → 238,7 |
fs_node_t *tmp = NULL; |
if (cur->mp_data.mp_active) { |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_LOOKUP, |
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); |
272,9 → 273,9 |
else |
next--; |
ipc_forward_slow(rid, tmp->mp_data.phone, VFS_LOOKUP, |
next, last, tmp->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
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) |
428,12 → 429,42 |
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_OPEN_NODE request. |
* @param request VFS_OPEN_NODE request data itself. |
* @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, |
/branches/dd/uspace/lib/libfs/libfs.h |
---|
84,6 → 84,7 |
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 *); |
/branches/dd/uspace/lib/libblock/libblock.c |
---|
46,13 → 46,13 |
#include <ipc/ipc.h> |
#include <as.h> |
#include <assert.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <adt/hash_table.h> |
#include <mem.h> |
/** Lock protecting the device connection list */ |
static futex_t dcl_lock = FUTEX_INITIALIZER; |
static FIBRIL_MUTEX_INITIALIZE(dcl_lock); |
/** Device connection list head. */ |
static LIST_INITIALIZE(dcl_head); |
60,11 → 60,13 |
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2) |
typedef struct { |
futex_t lock; |
fibril_mutex_t lock; |
size_t block_size; /**< Block size. */ |
unsigned block_count; /**< Total number of blocks. */ |
unsigned blocks_cached; /**< Number of cached blocks. */ |
hash_table_t block_hash; |
link_t free_head; |
enum cache_mode mode; |
} cache_t; |
typedef struct { |
71,6 → 73,7 |
link_t link; |
dev_handle_t dev_handle; |
int dev_phone; |
fibril_mutex_t com_area_lock; |
void *com_area; |
size_t com_size; |
void *bb_buf; |
79,19 → 82,22 |
cache_t *cache; |
} devcon_t; |
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size); |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size); |
static devcon_t *devcon_search(dev_handle_t dev_handle) |
{ |
link_t *cur; |
futex_down(&dcl_lock); |
fibril_mutex_lock(&dcl_lock); |
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
devcon_t *devcon = list_get_instance(cur, devcon_t, link); |
if (devcon->dev_handle == dev_handle) { |
futex_up(&dcl_lock); |
fibril_mutex_unlock(&dcl_lock); |
return devcon; |
} |
} |
futex_up(&dcl_lock); |
fibril_mutex_unlock(&dcl_lock); |
return NULL; |
} |
108,6 → 114,7 |
link_initialize(&devcon->link); |
devcon->dev_handle = dev_handle; |
devcon->dev_phone = dev_phone; |
fibril_mutex_initialize(&devcon->com_area_lock); |
devcon->com_area = com_area; |
devcon->com_size = com_size; |
devcon->bb_buf = NULL; |
115,25 → 122,25 |
devcon->bb_size = 0; |
devcon->cache = NULL; |
futex_down(&dcl_lock); |
fibril_mutex_lock(&dcl_lock); |
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
devcon_t *d = list_get_instance(cur, devcon_t, link); |
if (d->dev_handle == dev_handle) { |
futex_up(&dcl_lock); |
fibril_mutex_unlock(&dcl_lock); |
free(devcon); |
return EEXIST; |
} |
} |
list_append(&devcon->link, &dcl_head); |
futex_up(&dcl_lock); |
fibril_mutex_unlock(&dcl_lock); |
return EOK; |
} |
static void devcon_remove(devcon_t *devcon) |
{ |
futex_down(&dcl_lock); |
fibril_mutex_lock(&dcl_lock); |
list_remove(&devcon->link); |
futex_up(&dcl_lock); |
fibril_mutex_unlock(&dcl_lock); |
} |
int block_init(dev_handle_t dev_handle, size_t com_size) |
207,14 → 214,16 |
if (!bb_buf) |
return ENOMEM; |
off_t bufpos = 0; |
size_t buflen = 0; |
rc = block_read(dev_handle, &bufpos, &buflen, &off, |
bb_buf, size, size); |
fibril_mutex_lock(&devcon->com_area_lock); |
rc = read_block(devcon, 0, size); |
if (rc != EOK) { |
fibril_mutex_unlock(&devcon->com_area_lock); |
free(bb_buf); |
return rc; |
} |
memcpy(bb_buf, devcon->com_area, size); |
fibril_mutex_unlock(&devcon->com_area_lock); |
devcon->bb_buf = bb_buf; |
devcon->bb_off = off; |
devcon->bb_size = size; |
250,7 → 259,8 |
.remove_callback = cache_remove_callback |
}; |
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks) |
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks, |
enum cache_mode mode) |
{ |
devcon_t *devcon = devcon_search(dev_handle); |
cache_t *cache; |
262,10 → 272,12 |
if (!cache) |
return ENOMEM; |
futex_initialize(&cache->lock, 1); |
fibril_mutex_initialize(&cache->lock); |
list_initialize(&cache->free_head); |
cache->block_size = size; |
cache->block_count = blocks; |
cache->blocks_cached = 0; |
cache->mode = mode; |
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1, |
&cache_ops)) { |
277,17 → 289,23 |
return EOK; |
} |
#define CACHE_LO_WATERMARK 10 |
#define CACHE_HI_WATERMARK 20 |
static bool cache_can_grow(cache_t *cache) |
{ |
if (cache->blocks_cached < CACHE_LO_WATERMARK) |
return true; |
if (!list_empty(&cache->free_head)) |
return false; |
return true; |
} |
static void block_initialize(block_t *b) |
{ |
futex_initialize(&b->lock, 1); |
fibril_mutex_initialize(&b->lock); |
b->refcnt = 1; |
b->dirty = false; |
rwlock_initialize(&b->contents_lock); |
fibril_rwlock_initialize(&b->contents_lock); |
link_initialize(&b->free_link); |
link_initialize(&b->hash_link); |
} |
309,6 → 327,7 |
block_t *b; |
link_t *l; |
unsigned long key = boff; |
bn_t oboff; |
devcon = devcon_search(dev_handle); |
316,7 → 335,7 |
assert(devcon->cache); |
cache = devcon->cache; |
futex_down(&cache->lock); |
fibril_mutex_lock(&cache->lock); |
l = hash_table_find(&cache->block_hash, &key); |
if (l) { |
/* |
323,19 → 342,16 |
* We found the block in the cache. |
*/ |
b = hash_table_get_instance(l, block_t, hash_link); |
futex_down(&b->lock); |
fibril_mutex_lock(&b->lock); |
if (b->refcnt++ == 0) |
list_remove(&b->free_link); |
futex_up(&b->lock); |
futex_up(&cache->lock); |
fibril_mutex_unlock(&b->lock); |
fibril_mutex_unlock(&cache->lock); |
} else { |
/* |
* The block was not found in the cache. |
*/ |
int rc; |
off_t bufpos = 0; |
size_t buflen = 0; |
off_t pos = boff * cache->block_size; |
bool sync = false; |
if (cache_can_grow(cache)) { |
352,6 → 368,7 |
free(b); |
goto recycle; |
} |
cache->blocks_cached++; |
} else { |
/* |
* Try to recycle a block from the free list. |
361,8 → 378,9 |
assert(!list_empty(&cache->free_head)); |
l = cache->free_head.next; |
list_remove(l); |
b = hash_table_get_instance(l, block_t, hash_link); |
b = list_get_instance(l, block_t, free_link); |
sync = b->dirty; |
oboff = b->boff; |
temp_key = b->boff; |
hash_table_remove(&cache->block_hash, &temp_key, 1); |
} |
378,8 → 396,8 |
* kill concurent operations on the cache while doing I/O on the |
* block. |
*/ |
futex_down(&b->lock); |
futex_up(&cache->lock); |
fibril_mutex_lock(&b->lock); |
fibril_mutex_unlock(&cache->lock); |
if (sync) { |
/* |
386,7 → 404,11 |
* The block is dirty and needs to be written back to |
* the device before we can read in the new contents. |
*/ |
abort(); /* TODO: block_write() */ |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, b->data, b->size); |
rc = write_block(devcon, oboff, cache->block_size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
if (!(flags & BLOCK_FLAGS_NOREAD)) { |
/* |
393,12 → 415,14 |
* The block contains old or no data. We need to read |
* the new contents from the device. |
*/ |
rc = block_read(dev_handle, &bufpos, &buflen, &pos, |
b->data, cache->block_size, cache->block_size); |
fibril_mutex_lock(&devcon->com_area_lock); |
rc = read_block(devcon, b->boff, cache->block_size); |
assert(rc == EOK); |
memcpy(b->data, devcon->com_area, cache->block_size); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
futex_up(&b->lock); |
fibril_mutex_unlock(&b->lock); |
} |
return b; |
} |
413,25 → 437,62 |
{ |
devcon_t *devcon = devcon_search(block->dev_handle); |
cache_t *cache; |
int rc; |
assert(devcon); |
assert(devcon->cache); |
cache = devcon->cache; |
futex_down(&cache->lock); |
futex_down(&block->lock); |
fibril_mutex_lock(&cache->lock); |
fibril_mutex_lock(&block->lock); |
if (!--block->refcnt) { |
/* |
* Last reference to the block was dropped, put the block on the |
* free list. |
* Last reference to the block was dropped. Either free the |
* block or put it on the free list. |
*/ |
if (cache->blocks_cached > CACHE_HI_WATERMARK) { |
/* |
* Currently there are too many cached blocks. |
*/ |
if (block->dirty) { |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, block->data, |
block->size); |
rc = write_block(devcon, block->boff, |
block->size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
} |
/* |
* Take the block out of the cache and free it. |
*/ |
unsigned long key = block->boff; |
hash_table_remove(&cache->block_hash, &key, 1); |
free(block); |
free(block->data); |
cache->blocks_cached--; |
fibril_mutex_unlock(&cache->lock); |
return; |
} |
/* |
* Put the block on the free list. |
*/ |
list_append(&block->free_link, &cache->free_head); |
if (cache->mode != CACHE_MODE_WB && block->dirty) { |
fibril_mutex_lock(&devcon->com_area_lock); |
memcpy(devcon->com_area, block->data, block->size); |
rc = write_block(devcon, block->boff, block->size); |
assert(rc == EOK); |
fibril_mutex_unlock(&devcon->com_area_lock); |
block->dirty = false; |
} |
} |
futex_up(&block->lock); |
futex_up(&cache->lock); |
fibril_mutex_unlock(&block->lock); |
fibril_mutex_unlock(&cache->lock); |
} |
/** Read data from a block device. |
/** Read sequential data from a block device. |
* |
* @param dev_handle Device handle of the block device. |
* @param bufpos Pointer to the first unread valid offset within the |
445,9 → 506,8 |
* |
* @return EOK on success or a negative return code on failure. |
*/ |
int |
block_read(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_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen, |
off_t *pos, void *dst, size_t size, size_t block_size) |
{ |
off_t offset = 0; |
size_t left = size; |
454,6 → 514,7 |
devcon_t *devcon = devcon_search(dev_handle); |
assert(devcon); |
fibril_mutex_lock(&devcon->com_area_lock); |
while (left > 0) { |
size_t rd; |
474,21 → 535,70 |
left -= rd; |
} |
if (*bufpos == *buflen) { |
if (*bufpos == (off_t) *buflen) { |
/* Refill the communication buffer with a new block. */ |
ipcarg_t retval; |
int rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, |
*pos / block_size, block_size, &retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : retval); |
int rc; |
rc = read_block(devcon, *pos / block_size, block_size); |
if (rc != EOK) { |
fibril_mutex_unlock(&devcon->com_area_lock); |
return rc; |
} |
*bufpos = 0; |
*buflen = block_size; |
} |
} |
fibril_mutex_unlock(&devcon->com_area_lock); |
return EOK; |
} |
/** Read block from block device. |
* |
* @param devcon Device connection. |
* @param boff Block index. |
* @param block_size Block size. |
* @param src Buffer for storing the data. |
* |
* @return EOK on success or negative error code on failure. |
*/ |
static int read_block(devcon_t *devcon, bn_t boff, size_t block_size) |
{ |
ipcarg_t retval; |
int rc; |
assert(devcon); |
rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
return EOK; |
} |
/** Write block to block device. |
* |
* @param devcon Device connection. |
* @param boff Block index. |
* @param block_size Block size. |
* @param src Buffer containing the data to write. |
* |
* @return EOK on success or negative error code on failure. |
*/ |
static int write_block(devcon_t *devcon, bn_t boff, size_t block_size) |
{ |
ipcarg_t retval; |
int rc; |
assert(devcon); |
rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size, |
&retval); |
if ((rc != EOK) || (retval != EOK)) |
return (rc != EOK ? rc : (int) retval); |
return EOK; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libblock/libblock.h |
---|
39,8 → 39,7 |
#include <stdint.h> |
#include "../../srv/vfs/vfs.h" |
#include <futex.h> |
#include <rwlock.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <adt/list.h> |
63,14 → 62,14 |
typedef unsigned bn_t; /**< Block number type. */ |
typedef struct block { |
/** Futex protecting the reference count. */ |
futex_t lock; |
/** Mutex protecting the reference count. */ |
fibril_mutex_t lock; |
/** Number of references to the block_t structure. */ |
unsigned refcnt; |
/** If true, the block needs to be written back to the block device. */ |
bool dirty; |
/** Readers / Writer lock protecting the contents of the block. */ |
rwlock_t contents_lock; |
fibril_rwlock_t contents_lock; |
/** Handle of the device where the block resides. */ |
dev_handle_t dev_handle; |
/** Block offset on the block device. Counted in 'size'-byte blocks. */ |
85,6 → 84,14 |
void *data; |
} block_t; |
/** Caching mode */ |
enum cache_mode { |
/** Write-Through */ |
CACHE_MODE_WT, |
/** Write-Back */ |
CACHE_MODE_WB |
}; |
extern int block_init(dev_handle_t, size_t); |
extern void block_fini(dev_handle_t); |
91,13 → 98,13 |
extern int block_bb_read(dev_handle_t, off_t, size_t); |
extern void *block_bb_get(dev_handle_t); |
extern int block_cache_init(dev_handle_t, size_t, unsigned); |
extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode); |
extern block_t *block_get(dev_handle_t, bn_t, int flags); |
extern block_t *block_get(dev_handle_t, bn_t, int); |
extern void block_put(block_t *); |
extern int block_read(dev_handle_t, off_t *, size_t *, off_t *, void *, size_t, |
size_t); |
extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *, |
size_t, size_t); |
#endif |
/branches/dd/uspace/lib/softfloat/include/sftypes.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup softfloat |
/** @addtogroup softfloat |
* @{ |
*/ |
/** @file |
41,40 → 41,40 |
typedef union { |
float f; |
uint32_t binary; |
struct { |
#if defined(ARCH_IS_BIG_ENDIAN) |
uint32_t sign:1; |
uint32_t exp:8; |
uint32_t fraction:23; |
#elif defined(ARCH_IS_LITTLE_ENDIAN) |
uint32_t fraction:23; |
uint32_t exp:8; |
uint32_t sign:1; |
#else |
#error "Unknown endians." |
struct { |
#if defined(__BE__) |
uint32_t sign : 1; |
uint32_t exp : 8; |
uint32_t fraction : 23; |
#elif defined(__LE__) |
uint32_t fraction : 23; |
uint32_t exp : 8; |
uint32_t sign : 1; |
#else |
#error Unknown endianess |
#endif |
} parts __attribute__ ((packed)); |
} float32; |
} float32; |
typedef union { |
double d; |
uint64_t binary; |
struct { |
#if defined(ARCH_IS_BIG_ENDIAN) |
uint64_t sign:1; |
uint64_t exp:11; |
uint64_t fraction:52; |
#elif defined(ARCH_IS_LITTLE_ENDIAN) |
uint64_t fraction:52; |
uint64_t exp:11; |
uint64_t sign:1; |
#else |
#error "Unknown endians." |
struct { |
#if defined(__BE__) |
uint64_t sign : 1; |
uint64_t exp : 11; |
uint64_t fraction : 52; |
#elif defined(__LE__) |
uint64_t fraction : 52; |
uint64_t exp : 11; |
uint64_t sign : 1; |
#else |
#error Unknown endianess |
#endif |
} parts __attribute__ ((packed)); |
} float64; |
} parts __attribute__ ((packed)); |
} float64; |
#define FLOAT32_MAX 0x7f800000 |
#define FLOAT32_MIN 0xff800000 |
109,7 → 109,5 |
#endif |
/** @} |
/** @} |
*/ |
/branches/dd/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/dd/uspace/lib/libc/malloc/malloc.c |
---|
File deleted |
/branches/dd/uspace/lib/libc/include/byteorder.h |
---|
35,48 → 35,47 |
#ifndef LIBC_BYTEORDER_H_ |
#define LIBC_BYTEORDER_H_ |
#include <libarch/byteorder.h> |
#include <stdint.h> |
#if !(defined(ARCH_IS_BIG_ENDIAN) ^ defined(ARCH_IS_LITTLE_ENDIAN)) |
#error The architecture must be either big-endian or little-endian. |
#if !(defined(__BE__) ^ defined(__LE__)) |
#error The architecture must be either big-endian or little-endian. |
#endif |
#ifdef ARCH_IS_BIG_ENDIAN |
#ifdef __BE__ |
#define uint16_t_le2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_le2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_le2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_le2host(n) (uint16_t_byteorder_swap(n)) |
#define uint32_t_le2host(n) (uint32_t_byteorder_swap(n)) |
#define uint64_t_le2host(n) (uint64_t_byteorder_swap(n)) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define uint16_t_be2host(n) (n) |
#define uint32_t_be2host(n) (n) |
#define uint64_t_be2host(n) (n) |
#define host2uint16_t_le(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_le(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_le(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_le(n) (uint16_t_byteorder_swap(n)) |
#define host2uint32_t_le(n) (uint32_t_byteorder_swap(n)) |
#define host2uint64_t_le(n) (uint64_t_byteorder_swap(n)) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#define host2uint16_t_be(n) (n) |
#define host2uint32_t_be(n) (n) |
#define host2uint64_t_be(n) (n) |
#else |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_le2host(n) (n) |
#define uint32_t_le2host(n) (n) |
#define uint64_t_le2host(n) (n) |
#define uint16_t_be2host(n) uint16_t_byteorder_swap(n) |
#define uint32_t_be2host(n) uint32_t_byteorder_swap(n) |
#define uint64_t_be2host(n) uint64_t_byteorder_swap(n) |
#define uint16_t_be2host(n) (uint16_t_byteorder_swap(n)) |
#define uint32_t_be2host(n) (uint32_t_byteorder_swap(n)) |
#define uint64_t_be2host(n) (uint64_t_byteorder_swap(n)) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_le(n) (n) |
#define host2uint32_t_le(n) (n) |
#define host2uint64_t_le(n) (n) |
#define host2uint16_t_be(n) uint16_t_byteorder_swap(n) |
#define host2uint32_t_be(n) uint32_t_byteorder_swap(n) |
#define host2uint64_t_be(n) uint64_t_byteorder_swap(n) |
#define host2uint16_t_be(n) (uint16_t_byteorder_swap(n)) |
#define host2uint32_t_be(n) (uint32_t_byteorder_swap(n)) |
#define host2uint64_t_be(n) (uint64_t_byteorder_swap(n)) |
#endif |
/branches/dd/uspace/lib/libc/include/getopt.h |
---|
58,7 → 58,7 |
}; |
/* HelenOS Port - These need to be exposed for legacy getopt() */ |
extern char *optarg; |
extern const char *optarg; |
extern int optind, opterr, optopt; |
extern int optreset; |
/branches/dd/uspace/lib/libc/include/string.h |
---|
40,7 → 40,6 |
#include <bool.h> |
#define U_SPECIAL '?' |
#define U_BOM 0xfeff |
/** No size limit constant */ |
#define STR_NO_LIMIT ((size_t) -1) |
/branches/dd/uspace/lib/libc/include/malloc.h |
---|
1,537 → 1,51 |
/* |
Default header file for malloc-2.8.x, written by Doug Lea |
and released to the public domain, as explained at |
http://creativecommons.org/licenses/publicdomain. |
last update: Mon Aug 15 08:55:52 2005 Doug Lea (dl at gee) |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
This header is for ANSI C/C++ only. You can set any of |
the following #defines before including: |
* If USE_DL_PREFIX is defined, it is assumed that malloc.c |
was also compiled with this option, so all routines |
have names starting with "dl". |
* If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this |
file will be #included AFTER <malloc.h>. This is needed only if |
your system defines a struct mallinfo that is incompatible with the |
standard one declared here. Otherwise, you can include this file |
INSTEAD of your system system <malloc.h>. At least on ANSI, all |
declarations should be compatible with system versions |
* If MSPACES is defined, declarations for mspace versions are included. |
*/ |
#ifndef MALLOC_280_H |
#define MALLOC_280_H |
#ifdef __cplusplus |
extern "C" { |
#endif |
#include <stddef.h> /* for size_t */ |
#if !ONLY_MSPACES |
#ifndef USE_DL_PREFIX |
#define dlcalloc calloc |
#define dlfree free |
#define dlmalloc malloc |
#define dlmemalign memalign |
#define dlrealloc realloc |
#define dlvalloc valloc |
#define dlpvalloc pvalloc |
#define dlmallinfo mallinfo |
#define dlmallopt mallopt |
#define dlmalloc_trim malloc_trim |
#define dlmalloc_stats malloc_stats |
#define dlmalloc_usable_size malloc_usable_size |
#define dlmalloc_footprint malloc_footprint |
#define dlmalloc_max_footprint malloc_max_footprint |
#define dlindependent_calloc independent_calloc |
#define dlindependent_comalloc independent_comalloc |
#endif /* USE_DL_PREFIX */ |
/* |
malloc(size_t n) |
Returns a pointer to a newly allocated chunk of at least n bytes, or |
null if no space is available, in which case errno is set to ENOMEM |
on ANSI C systems. |
If n is zero, malloc returns a minimum-sized chunk. (The minimum |
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit |
systems.) Note that size_t is an unsigned type, so calls with |
arguments that would be negative if signed are interpreted as |
requests for huge amounts of space, which will often fail. The |
maximum supported value of n differs across systems, but is in all |
cases less than the maximum representable value of a size_t. |
*/ |
void* dlmalloc(size_t); |
/* |
free(void* p) |
Releases the chunk of memory pointed to by p, that had been previously |
allocated using malloc or a related routine such as realloc. |
It has no effect if p is null. If p was not malloced or already |
freed, free(p) will by default cuase the current program to abort. |
*/ |
void dlfree(void*); |
/* |
calloc(size_t n_elements, size_t element_size); |
Returns a pointer to n_elements * element_size bytes, with all locations |
set to zero. |
*/ |
void* dlcalloc(size_t, size_t); |
/* |
realloc(void* p, size_t n) |
Returns a pointer to a chunk of size n that contains the same data |
as does chunk p up to the minimum of (n, p's size) bytes, or null |
if no space is available. |
The returned pointer may or may not be the same as p. The algorithm |
prefers extending p in most cases when possible, otherwise it |
employs the equivalent of a malloc-copy-free sequence. |
If p is null, realloc is equivalent to malloc. |
If space is not available, realloc returns null, errno is set (if on |
ANSI) and p is NOT freed. |
if n is for fewer bytes than already held by p, the newly unused |
space is lopped off and freed if possible. realloc with a size |
argument of zero (re)allocates a minimum-sized chunk. |
The old unix realloc convention of allowing the last-free'd chunk |
to be used as an argument to realloc is not supported. |
*/ |
void* dlrealloc(void*, size_t); |
/* |
memalign(size_t alignment, size_t n); |
Returns a pointer to a newly allocated chunk of n bytes, aligned |
in accord with the alignment argument. |
The alignment argument should be a power of two. If the argument is |
not a power of two, the nearest greater power is used. |
8-byte alignment is guaranteed by normal malloc calls, so don't |
bother calling memalign with an argument of 8 or less. |
Overreliance on memalign is a sure way to fragment space. |
*/ |
void* dlmemalign(size_t, size_t); |
/* |
valloc(size_t n); |
Equivalent to memalign(pagesize, n), where pagesize is the page |
size of the system. If the pagesize is unknown, 4096 is used. |
*/ |
void* dlvalloc(size_t); |
/* |
mallopt(int parameter_number, int parameter_value) |
Sets tunable parameters The format is to provide a |
(parameter-number, parameter-value) pair. mallopt then sets the |
corresponding parameter to the argument value if it can (i.e., so |
long as the value is meaningful), and returns 1 if successful else |
0. SVID/XPG/ANSI defines four standard param numbers for mallopt, |
normally defined in malloc.h. None of these are use in this malloc, |
so setting them has no effect. But this malloc also supports other |
options in mallopt: |
Symbol param # default allowed param values |
M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming) |
M_GRANULARITY -2 page size any power of 2 >= page size |
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) |
*/ |
int dlmallopt(int, int); |
#define M_TRIM_THRESHOLD (-1) |
#define M_GRANULARITY (-2) |
#define M_MMAP_THRESHOLD (-3) |
/* |
malloc_footprint(); |
Returns the number of bytes obtained from the system. The total |
number of bytes allocated by malloc, realloc etc., is less than this |
value. Unlike mallinfo, this function returns only a precomputed |
result, so can be called frequently to monitor memory consumption. |
Even if locks are otherwise defined, this function does not use them, |
so results might not be up to date. |
*/ |
size_t dlmalloc_footprint(void); |
size_t dlmalloc_max_footprint(void); |
#if !NO_MALLINFO |
/* |
mallinfo() |
Returns (by copy) a struct containing various summary statistics: |
arena: current total non-mmapped bytes allocated from system |
ordblks: the number of free chunks |
smblks: always zero. |
hblks: current number of mmapped regions |
hblkhd: total bytes held in mmapped regions |
usmblks: the maximum total allocated space. This will be greater |
than current total if trimming has occurred. |
fsmblks: always zero |
uordblks: current total allocated space (normal or mmapped) |
fordblks: total free space |
keepcost: the maximum number of bytes that could ideally be released |
back to system via malloc_trim. ("ideally" means that |
it ignores page restrictions etc.) |
Because these fields are ints, but internal bookkeeping may |
be kept as longs, the reported values may wrap around zero and |
thus be inaccurate. |
*/ |
#ifndef HAVE_USR_INCLUDE_MALLOC_H |
#ifndef _MALLOC_H |
#ifndef MALLINFO_FIELD_TYPE |
#define MALLINFO_FIELD_TYPE size_t |
#endif /* MALLINFO_FIELD_TYPE */ |
struct mallinfo { |
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ |
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ |
MALLINFO_FIELD_TYPE smblks; /* always 0 */ |
MALLINFO_FIELD_TYPE hblks; /* always 0 */ |
MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ |
MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ |
MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ |
MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ |
MALLINFO_FIELD_TYPE fordblks; /* total free space */ |
MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ |
}; |
#endif /* _MALLOC_H */ |
#endif /* HAVE_USR_INCLUDE_MALLOC_H */ |
struct mallinfo dlmallinfo(void); |
#endif /* NO_MALLINFO */ |
/* |
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); |
independent_calloc is similar to calloc, but instead of returning a |
single cleared space, it returns an array of pointers to n_elements |
independent elements that can hold contents of size elem_size, each |
of which starts out cleared, and can be independently freed, |
realloc'ed etc. The elements are guaranteed to be adjacently |
allocated (this is not guaranteed to occur with multiple callocs or |
mallocs), which may also improve cache locality in some |
applications. |
The "chunks" argument is optional (i.e., may be null, which is |
probably the most typical usage). If it is null, the returned array |
is itself dynamically allocated and should also be freed when it is |
no longer needed. Otherwise, the chunks array must be of at least |
n_elements in length. It is filled in with the pointers to the |
chunks. |
In either case, independent_calloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and "chunks" |
is null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use regular calloc and assign pointers into this |
space to represent elements. (In this case though, you cannot |
independently free elements.) |
independent_calloc simplifies and speeds up implementations of many |
kinds of pools. It may also be useful when constructing large data |
structures that initially have a fixed number of fixed-sized nodes, |
but the number is not known at compile time, and some of the nodes |
may later need to be freed. For example: |
struct Node { int item; struct Node* next; }; |
struct Node* build_list() { |
struct Node** pool; |
int n = read_number_of_nodes_needed(); |
if (n <= 0) return 0; |
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); |
if (pool == 0) die(); |
// organize into a linked list... |
struct Node* first = pool[0]; |
for (i = 0; i < n-1; ++i) |
pool[i]->next = pool[i+1]; |
free(pool); // Can now free the array (or not, if it is needed later) |
return first; |
} |
*/ |
void** dlindependent_calloc(size_t, size_t, void**); |
/* |
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); |
independent_comalloc allocates, all at once, a set of n_elements |
chunks with sizes indicated in the "sizes" array. It returns |
an array of pointers to these elements, each of which can be |
independently freed, realloc'ed etc. The elements are guaranteed to |
be adjacently allocated (this is not guaranteed to occur with |
multiple callocs or mallocs), which may also improve cache locality |
in some applications. |
The "chunks" argument is optional (i.e., may be null). If it is null |
the returned array is itself dynamically allocated and should also |
be freed when it is no longer needed. Otherwise, the chunks array |
must be of at least n_elements in length. It is filled in with the |
pointers to the chunks. |
In either case, independent_comalloc returns this pointer array, or |
null if the allocation failed. If n_elements is zero and chunks is |
null, it returns a chunk representing an array with zero elements |
(which should be freed if not wanted). |
Each element must be individually freed when it is no longer |
needed. If you'd like to instead be able to free all at once, you |
should instead use a single regular malloc, and assign pointers at |
particular offsets in the aggregate space. (In this case though, you |
cannot independently free elements.) |
independent_comallac differs from independent_calloc in that each |
element may have a different size, and also that it does not |
automatically clear elements. |
independent_comalloc can be used to speed up allocation in cases |
where several structs or objects must always be allocated at the |
same time. For example: |
struct Head { ... } |
struct Foot { ... } |
void send_message(char* msg) { |
int msglen = strlen(msg); |
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; |
void* chunks[3]; |
if (independent_comalloc(3, sizes, chunks) == 0) |
die(); |
struct Head* head = (struct Head*)(chunks[0]); |
char* body = (char*)(chunks[1]); |
struct Foot* foot = (struct Foot*)(chunks[2]); |
// ... |
} |
In general though, independent_comalloc is worth using only for |
larger values of n_elements. For small values, you probably won't |
detect enough difference from series of malloc calls to bother. |
Overuse of independent_comalloc can increase overall memory usage, |
since it cannot reuse existing noncontiguous small chunks that |
might be available for some of the elements. |
*/ |
void** dlindependent_comalloc(size_t, size_t*, void**); |
/* |
pvalloc(size_t n); |
Equivalent to valloc(minimum-page-that-holds(n)), that is, |
round up n to nearest pagesize. |
/** @addtogroup libc |
* @{ |
*/ |
void* dlpvalloc(size_t); |
/** @file |
*/ |
/* |
malloc_trim(size_t pad); |
#ifndef LIBC_MALLOC_H_ |
#define LIBC_MALLOC_H_ |
If possible, gives memory back to the system (via negative arguments |
to sbrk) if there is unused memory at the `high' end of the malloc |
pool or in unused MMAP segments. You can call this after freeing |
large blocks of memory to potentially reduce the system-level memory |
requirements of a program. However, it cannot guarantee to reduce |
memory. Under some allocation patterns, some large free blocks of |
memory will be locked between two used chunks, so they cannot be |
given back to the system. |
#include <sys/types.h> |
The `pad' argument to malloc_trim represents the amount of free |
trailing space to leave untrimmed. If this argument is zero, only |
the minimum amount of memory to maintain internal data structures |
will be left. Non-zero arguments can be supplied to maintain enough |
trailing space to service future expected allocations without having |
to re-obtain memory from the system. |
extern void __heap_init(void); |
extern uintptr_t get_max_heap_addr(void); |
Malloc_trim returns 1 if it actually released any memory, else 0. |
*/ |
int dlmalloc_trim(size_t); |
extern void *malloc(const size_t size); |
extern void *memalign(const size_t align, const size_t size); |
extern void *realloc(const void *addr, const size_t size); |
extern void free(const void *addr); |
/* |
malloc_usable_size(void* p); |
Returns the number of bytes you can actually use in |
an allocated chunk, which may be more than you requested (although |
often not) due to alignment and minimum size constraints. |
You can use this many bytes without worrying about |
overwriting other allocated objects. This is not a particularly great |
programming practice. malloc_usable_size can be more useful in |
debugging and assertions, for example: |
p = malloc(n); |
assert(malloc_usable_size(p) >= 256); |
*/ |
size_t dlmalloc_usable_size(void*); |
/* |
malloc_stats(); |
Prints on stderr the amount of space obtained from the system (both |
via sbrk and mmap), the maximum amount (which may be more than |
current if malloc_trim and/or munmap got called), and the current |
number of bytes allocated via malloc (or realloc, etc) but not yet |
freed. Note that this is the number of bytes allocated, not the |
number requested. It will be larger than the number requested |
because of alignment and bookkeeping overhead. Because it includes |
alignment wastage as being in use, this figure may be greater than |
zero even when no user-level chunks are allocated. |
The reported current and maximum system memory can be inaccurate if |
a program makes other calls to system memory allocation functions |
(normally sbrk) outside of malloc. |
malloc_stats prints only the most commonly interesting statistics. |
More information can be obtained by calling mallinfo. |
*/ |
void dlmalloc_stats(void); |
#endif /* !ONLY_MSPACES */ |
#if MSPACES |
/* |
mspace is an opaque type representing an independent |
region of space that supports mspace_malloc, etc. |
*/ |
typedef void* mspace; |
/* |
create_mspace creates and returns a new independent space with the |
given initial capacity, or, if 0, the default granularity size. It |
returns null if there is no system memory available to create the |
space. If argument locked is non-zero, the space uses a separate |
lock to control access. The capacity of the space will grow |
dynamically as needed to service mspace_malloc requests. You can |
control the sizes of incremental increases of this space by |
compiling with a different DEFAULT_GRANULARITY or dynamically |
setting with mallopt(M_GRANULARITY, value). |
*/ |
mspace create_mspace(size_t capacity, int locked); |
/* |
destroy_mspace destroys the given space, and attempts to return all |
of its memory back to the system, returning the total number of |
bytes freed. After destruction, the results of access to all memory |
used by the space become undefined. |
*/ |
size_t destroy_mspace(mspace msp); |
/* |
create_mspace_with_base uses the memory supplied as the initial base |
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this |
space is used for bookkeeping, so the capacity must be at least this |
large. (Otherwise 0 is returned.) When this initial space is |
exhausted, additional memory will be obtained from the system. |
Destroying this space will deallocate all additionally allocated |
space (if possible) but not the initial base. |
*/ |
mspace create_mspace_with_base(void* base, size_t capacity, int locked); |
/* |
mspace_malloc behaves as malloc, but operates within |
the given space. |
*/ |
void* mspace_malloc(mspace msp, size_t bytes); |
/* |
mspace_free behaves as free, but operates within |
the given space. |
If compiled with FOOTERS==1, mspace_free is not actually needed. |
free may be called instead of mspace_free because freed chunks from |
any space are handled by their originating spaces. |
*/ |
void mspace_free(mspace msp, void* mem); |
/* |
mspace_realloc behaves as realloc, but operates within |
the given space. |
If compiled with FOOTERS==1, mspace_realloc is not actually |
needed. realloc may be called instead of mspace_realloc because |
realloced chunks from any space are handled by their originating |
spaces. |
*/ |
void* mspace_realloc(mspace msp, void* mem, size_t newsize); |
/* |
mspace_calloc behaves as calloc, but operates within |
the given space. |
*/ |
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); |
/* |
mspace_memalign behaves as memalign, but operates within |
the given space. |
*/ |
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); |
/* |
mspace_independent_calloc behaves as independent_calloc, but |
operates within the given space. |
*/ |
void** mspace_independent_calloc(mspace msp, size_t n_elements, |
size_t elem_size, void* chunks[]); |
/* |
mspace_independent_comalloc behaves as independent_comalloc, but |
operates within the given space. |
*/ |
void** mspace_independent_comalloc(mspace msp, size_t n_elements, |
size_t sizes[], void* chunks[]); |
/* |
mspace_footprint() returns the number of bytes obtained from the |
system for this space. |
*/ |
size_t mspace_footprint(mspace msp); |
#if !NO_MALLINFO |
/* |
mspace_mallinfo behaves as mallinfo, but reports properties of |
the given space. |
*/ |
struct mallinfo mspace_mallinfo(mspace msp); |
#endif /* NO_MALLINFO */ |
/* |
mspace_malloc_stats behaves as malloc_stats, but reports |
properties of the given space. |
*/ |
void mspace_malloc_stats(mspace msp); |
/* |
mspace_trim behaves as malloc_trim, but |
operates within the given space. |
*/ |
int mspace_trim(mspace msp, size_t pad); |
/* |
An alias for mallopt. |
*/ |
int mspace_mallopt(int, int); |
#endif /* MSPACES */ |
#ifdef __cplusplus |
}; /* end of extern "C" */ |
#endif |
#endif /* MALLOC_280_H */ |
/** @} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/vfs/vfs.h |
---|
55,8 → 55,8 |
extern int mount(const char *, const char *, const char *, const char *, |
unsigned int); |
extern void stdio_init(int filc, fdi_node_t *filv[]); |
extern void stdio_done(void); |
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); |
/branches/dd/uspace/lib/libc/include/async.h |
---|
43,15 → 43,10 |
typedef ipc_callid_t aid_t; |
typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call); |
typedef void (*async_pending_t)(void); |
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); |
static inline ipc_callid_t async_get_call(ipc_call_t *data) |
59,6 → 54,11 |
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 |
95,11 → 95,9 |
extern void async_usleep(suseconds_t timeout); |
extern void async_create_manager(void); |
extern void async_destroy_manager(void); |
extern 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); |
extern void async_set_pending(async_pending_t pend); |
/* Wrappers for simple communication */ |
#define async_msg_0(phone, method) \ |
/branches/dd/uspace/lib/libc/include/stdlib.h |
---|
38,10 → 38,10 |
#include <unistd.h> |
#include <malloc.h> |
#define abort() _exit(1) |
#define exit(status) _exit((status)) |
#define abort() _exit(1) |
#define exit(status) _exit((status)) |
#define RAND_MAX 714025 |
#define RAND_MAX 714025 |
extern long int random(void); |
extern void srandom(unsigned int seed); |
50,6 → 50,7 |
{ |
return random(); |
} |
static inline void srand(unsigned int seed) |
{ |
srandom(seed); |
/branches/dd/uspace/lib/libc/include/stdio.h |
---|
37,17 → 37,21 |
#include <sys/types.h> |
#include <stdarg.h> |
#include <string.h> |
#include <adt/list.h> |
#define EOF (-1) |
/** Default size for stream I/O buffers */ |
#define BUFSIZ 4096 |
#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 = 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 |
55,6 → 59,15 |
#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; |
73,6 → 86,15 |
/** 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; |
121,6 → 143,8 |
extern int ferror(FILE *); |
extern void clearerr(FILE *); |
extern void setvbuf(FILE *, void *, int, size_t); |
/* Misc file functions */ |
extern int rename(const char *, const char *); |
/branches/dd/uspace/lib/libc/include/bitops.h |
---|
26,7 → 26,7 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
42,10 → 42,10 |
* |
* If number is zero, it returns 0 |
*/ |
static inline int fnzb32(uint32_t arg) |
static inline unsigned int fnzb32(uint32_t arg) |
{ |
int n = 0; |
unsigned int n = 0; |
if (arg >> 16) { |
arg >>= 16; |
n += 16; |
74,19 → 74,22 |
return n; |
} |
static inline int fnzb64(uint64_t arg) |
static inline unsigned int fnzb64(uint64_t arg) |
{ |
int n = 0; |
unsigned int n = 0; |
if (arg >> 32) { |
arg >>= 32; |
n += 32; |
} |
return n + fnzb32((uint32_t) arg); |
return (n + fnzb32((uint32_t) arg)); |
} |
#define fnzb(x) fnzb32(x) |
static inline unsigned int fnzb(size_t arg) |
{ |
return fnzb64(arg); |
} |
#endif |
/branches/dd/uspace/lib/libc/include/task.h |
---|
39,11 → 39,18 |
typedef uint64_t task_id_t; |
typedef enum { |
TASK_EXIT_NORMAL, |
TASK_EXIT_UNEXPECTED |
} task_exit_t; |
extern task_id_t task_get_id(void); |
extern int task_set_name(const char *name); |
extern task_id_t task_spawn(const char *path, char *const argv[]); |
extern int task_wait(task_id_t id); |
extern int task_wait(task_id_t id, task_exit_t *texit, int *retval); |
extern int task_retval(int val); |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/unistd.h |
---|
65,7 → 65,6 |
extern int chdir(const char *); |
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/dd/uspace/lib/libc/include/fibril.h |
---|
75,7 → 75,7 |
/** Fibril-local variable specifier */ |
#define fibril_local __thread |
extern int context_save(context_t *c); |
extern int context_save(context_t *c) __attribute__ ((returns_twice)); |
extern void context_restore(context_t *c) __attribute__ ((noreturn)); |
extern fid_t fibril_create(int (*func)(void *), void *arg); |
/branches/dd/uspace/lib/libc/include/devmap.h |
---|
47,6 → 47,9 |
extern int devmap_device_get_handle(const char *, dev_handle_t *, unsigned int); |
extern int devmap_device_connect(dev_handle_t, unsigned int); |
extern int devmap_null_create(void); |
extern void devmap_null_destroy(int); |
extern ipcarg_t devmap_device_get_count(void); |
extern ipcarg_t devmap_device_get_devices(ipcarg_t, dev_desc_t *); |
/branches/dd/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/dd/uspace/lib/libc/include/io/console.h |
---|
43,6 → 43,13 |
KEY_RELEASE |
} console_ev_type_t; |
enum { |
CONSOLE_CCAP_NONE = 0, |
CONSOLE_CCAP_STYLE, |
CONSOLE_CCAP_INDEXED, |
CONSOLE_CCAP_RGB |
}; |
/** Console event structure. */ |
typedef struct { |
/** Press or release event. */ |
68,6 → 75,7 |
extern void console_set_rgb_color(int phone, int fg_color, int bg_color); |
extern void console_cursor_visibility(int phone, bool show); |
extern int console_get_color_cap(int phone, int *ccap); |
extern void console_kcon_enable(int phone); |
extern bool console_get_event(int phone, console_event_t *event); |
/branches/dd/uspace/lib/libc/include/adt/gcdlcm.h |
---|
0,0 → 1,73 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#ifndef LIBC_GCDLCM_H_ |
#define LIBC_GCDLCM_H_ |
#include <sys/types.h> |
#define DECLARE_GCD(type, name) \ |
static inline type name(type a, type b) \ |
{ \ |
if (a == 0) \ |
return b; \ |
\ |
while (b != 0) { \ |
if (a > b) \ |
a -= b; \ |
else \ |
b -= a; \ |
} \ |
\ |
return a; \ |
} |
#define DECLARE_LCM(type, name, gcd) \ |
static inline type name(type a, type b) \ |
{ \ |
return (a * b) / gcd(a, b); \ |
} |
DECLARE_GCD(uint32_t, gcd32); |
DECLARE_GCD(uint64_t, gcd64); |
DECLARE_GCD(size_t, gcd); |
DECLARE_LCM(uint32_t, lcm32, gcd32); |
DECLARE_LCM(uint64_t, lcm64, gcd64); |
DECLARE_LCM(size_t, lcm, gcd); |
#endif |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/include/macros.h |
---|
35,6 → 35,9 |
#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) |
/branches/dd/uspace/lib/libc/include/ipc/devmap.h |
---|
28,7 → 28,7 |
/** @addtogroup devmap |
* @{ |
*/ |
*/ |
#ifndef DEVMAP_DEVMAP_H_ |
#define DEVMAP_DEVMAP_H_ |
48,6 → 48,8 |
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_request_t; |
/branches/dd/uspace/lib/libc/include/ipc/vfs.h |
---|
57,36 → 57,40 |
} vfs_info_t; |
typedef enum { |
VFS_OPEN_NODE = IPC_FIRST_USER_METHOD, |
VFS_READ, |
VFS_WRITE, |
VFS_TRUNCATE, |
VFS_MOUNT, |
VFS_UNMOUNT, |
VFS_DEVICE, |
VFS_SYNC, |
VFS_CLOSE, |
VFS_LAST_CMN /* keep this the last member of this enum */ |
} vfs_request_cmn_t; |
VFS_IN_OPEN = IPC_FIRST_USER_METHOD, |
VFS_IN_OPEN_NODE, |
VFS_IN_READ, |
VFS_IN_WRITE, |
VFS_IN_SEEK, |
VFS_IN_TRUNCATE, |
VFS_IN_FSTAT, |
VFS_IN_CLOSE, |
VFS_IN_MOUNT, |
VFS_IN_UNMOUNT, |
VFS_IN_SYNC, |
VFS_IN_REGISTER, |
VFS_IN_MKDIR, |
VFS_IN_UNLINK, |
VFS_IN_RENAME, |
VFS_IN_STAT |
} vfs_in_request_t; |
typedef enum { |
VFS_LOOKUP = VFS_LAST_CMN, |
VFS_MOUNTED, |
VFS_DESTROY, |
VFS_LAST_CLNT /* keep this the last member of this enum */ |
} vfs_request_clnt_t; |
VFS_OUT_OPEN_NODE = IPC_FIRST_USER_METHOD, |
VFS_OUT_READ, |
VFS_OUT_WRITE, |
VFS_OUT_TRUNCATE, |
VFS_OUT_CLOSE, |
VFS_OUT_MOUNT, |
VFS_OUT_MOUNTED, |
VFS_OUT_UNMOUNT, |
VFS_OUT_SYNC, |
VFS_OUT_STAT, |
VFS_OUT_LOOKUP, |
VFS_OUT_DESTROY, |
VFS_OUT_LAST |
} vfs_out_request_t; |
typedef enum { |
VFS_REGISTER = VFS_LAST_CMN, |
VFS_OPEN, |
VFS_SEEK, |
VFS_MKDIR, |
VFS_UNLINK, |
VFS_RENAME, |
VFS_NODE, |
VFS_LAST_SRV /* keep this the last member of this enum */ |
} vfs_request_srv_t; |
/* |
* Lookup flags. |
*/ |
/branches/dd/uspace/lib/libc/include/ipc/ns.h |
---|
39,7 → 39,9 |
typedef enum { |
NS_PING = IPC_FIRST_USER_METHOD, |
NS_TASK_WAIT |
NS_TASK_WAIT, |
NS_ID_INTRO, |
NS_RETVAL |
} ns_request_t; |
#endif |
/branches/dd/uspace/lib/libc/include/ipc/console.h |
---|
39,7 → 39,8 |
#include <ipc/vfs.h> |
typedef enum { |
CONSOLE_GET_SIZE = VFS_LAST_SRV, |
CONSOLE_GET_SIZE = VFS_OUT_LAST, |
CONSOLE_GET_COLOR_CAP, |
CONSOLE_GET_EVENT, |
CONSOLE_GOTO, |
CONSOLE_CLEAR, |
/branches/dd/uspace/lib/libc/include/ipc/fb.h |
---|
41,6 → 41,7 |
FB_PUTCHAR = IPC_FIRST_USER_METHOD, |
FB_CLEAR, |
FB_GET_CSIZE, |
FB_GET_COLOR_CAP, |
FB_CURSOR_VISIBILITY, |
FB_CURSOR_GOTO, |
FB_SCROLL, |
71,6 → 72,13 |
FB_SCREEN_RECLAIM |
} fb_request_t; |
enum { |
FB_CCAP_NONE = 0, |
FB_CCAP_STYLE, |
FB_CCAP_INDEXED, |
FB_CCAP_RGB |
}; |
#endif |
/** @} |
/branches/dd/uspace/lib/libc/include/errno.h |
---|
35,12 → 35,13 |
#ifndef LIBC_ERRNO_H_ |
#define LIBC_ERRNO_H_ |
/* TODO: support threads/fibrils */ |
#include <kernel/errno.h> |
#include <fibril.h> |
extern int _errno; |
#define errno _errno |
#include <kernel/errno.h> |
#define EMFILE (-17) |
#define ENAMETOOLONG (-256) |
#define EISDIR (-257) |
/branches/dd/uspace/lib/libc/include/sys/stat.h |
---|
36,7 → 36,26 |
#define LIBC_SYS_STAT_H_ |
#include <sys/types.h> |
#include <bool.h> |
#include <ipc/vfs.h> |
#include <ipc/devmap.h> |
struct stat { |
fs_handle_t fs_handle; |
dev_handle_t dev_handle; |
fs_index_t index; |
unsigned lnkcnt; |
bool is_file; |
off_t size; |
union { |
struct { |
dev_handle_t device; |
} devfs_stat; |
}; |
}; |
extern int fstat(int, struct stat *); |
extern int stat(const char *, struct stat *); |
extern int mkdir(const char *, mode_t); |
#endif |
/branches/dd/uspace/lib/libc/Makefile.toolchain |
---|
27,9 → 27,10 |
# |
CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \ |
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32 -finput-charset=UTF-8 \ |
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \ |
-Werror-implicit-function-declaration -nostdlib -nostdinc -pipe -g |
-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \ |
-finput-charset=UTF-8 -fno-builtin -Wall -Wextra -Wno-unused-parameter \ |
-Wmissing-prototypes -Werror-implicit-function-declaration -nostdlib \ |
-nostdinc -pipe -g -D__$(ENDIANESS)__ |
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS = |
/branches/dd/uspace/lib/libc/generic/task.c |
---|
148,10 → 148,23 |
return 0; |
} |
int task_wait(task_id_t id) |
int task_wait(task_id_t id, task_exit_t *texit, int *retval) |
{ |
return (int) async_req_2_0(PHONE_NS, NS_TASK_WAIT, LOWER32(id), UPPER32(id)); |
ipcarg_t te, rv; |
int rc; |
rc = (int) async_req_2_2(PHONE_NS, NS_TASK_WAIT, LOWER32(id), |
UPPER32(id), &te, &rv); |
*texit = te; |
*retval = rv; |
return rc; |
} |
int task_retval(int val) |
{ |
return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/getopt.c |
---|
47,7 → 47,7 |
int optind = 1; /* index into parent argv vector */ |
int optopt = '?'; /* character checked for validity */ |
int optreset; /* reset getopt */ |
char *optarg; /* argument associated with option */ |
const char *optarg; /* argument associated with option */ |
#define IGNORE_FIRST (*options == '-' || *options == '+') |
162,7 → 162,7 |
char **nargv; |
const char *options; |
{ |
char *oli; /* option letter list index */ |
const char *oli; /* option letter list index */ |
int optchar; |
assert(nargv != NULL); |
275,7 → 275,7 |
} else { /* takes (optional) argument */ |
optarg = NULL; |
if (*place) /* no white space */ |
optarg = *place; |
optarg = place; |
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
else if (oli[1] != ':') { /* arg not optional */ |
if (++optind >= nargc) { /* no arg */ |
353,7 → 353,8 |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
char *current_argv, *has_equal; |
char *current_argv; |
const char *has_equal; |
size_t current_argv_len; |
int i, ambiguous, match; |
/branches/dd/uspace/lib/libc/generic/as.c |
---|
38,23 → 38,23 |
#include <align.h> |
#include <sys/types.h> |
#include <bitops.h> |
#include <malloc.h> |
/** |
* Either 4*256M on 32-bit architecures or 16*256M on 64-bit architectures. |
*/ |
#define MAX_HEAP_SIZE (sizeof(uintptr_t)<<28) |
/** Last position allocated by as_get_mappable_page */ |
static uintptr_t last_allocated = 0; |
/** Create address space area. |
* |
* @param address Virtual address where to place new address space area. |
* @param size Size of the area. |
* @param flags Flags describing type of the area. |
* @param size Size of the area. |
* @param flags Flags describing type of the area. |
* |
* @return address on success, (void *) -1 otherwise. |
* |
*/ |
void *as_area_create(void *address, size_t size, int flags) |
{ |
return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t ) address, |
return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t) address, |
(sysarg_t) size, (sysarg_t) flags); |
} |
61,15 → 61,16 |
/** Resize address space area. |
* |
* @param address Virtual address pointing into already existing address space |
* area. |
* @param size New requested size of the area. |
* @param flags Currently unused. |
* area. |
* @param size New requested size of the area. |
* @param flags Currently unused. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_resize(void *address, size_t size, int flags) |
{ |
return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t ) address, |
return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t) address, |
(sysarg_t) size, (sysarg_t) flags); |
} |
76,22 → 77,24 |
/** Destroy address space area. |
* |
* @param address Virtual address pointing into the address space area being |
* destroyed. |
* destroyed. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_destroy(void *address) |
{ |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address); |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t) address); |
} |
/** Change address-space area flags. |
* |
* @param address Virtual address pointing into the address space area being |
* modified. |
* @param flags New flags describing type of the area. |
* modified. |
* @param flags New flags describing type of the area. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
* @return zero on success or a code from @ref errno.h on failure. |
* |
*/ |
int as_area_change_flags(void *address, int flags) |
{ |
99,101 → 102,29 |
(sysarg_t) flags); |
} |
static size_t heapsize = 0; |
static size_t maxheapsize = (size_t) (-1); |
static void *last_allocated = 0; |
/* Start of heap linker symbol */ |
extern char _heap; |
/** Sbrk emulation |
* |
* @param incr New area that should be allocated or negative, |
if it should be shrinked |
* @return Pointer to newly allocated area |
*/ |
void *sbrk(ssize_t incr) |
{ |
int rc; |
void *res; |
/* Check for invalid values */ |
if ((incr < 0) && (((size_t) -incr) > heapsize)) |
return NULL; |
/* Check for too large value */ |
if ((incr > 0) && (incr + heapsize < heapsize)) |
return NULL; |
/* Check for too small values */ |
if ((incr < 0) && (incr + heapsize > heapsize)) |
return NULL; |
/* Check for user limit */ |
if ((maxheapsize != (size_t) (-1)) && (heapsize + incr) > maxheapsize) |
return NULL; |
rc = as_area_resize(&_heap, heapsize + incr, 0); |
if (rc != 0) |
return NULL; |
/* Compute start of new area */ |
res = (void *) &_heap + heapsize; |
heapsize += incr; |
return res; |
} |
/** Set maximum heap size and return pointer just after the heap */ |
void *set_maxheapsize(size_t mhs) |
{ |
maxheapsize = mhs; |
/* Return pointer to area not managed by sbrk */ |
return ((void *) &_heap + maxheapsize); |
} |
/** Return pointer to some unmapped area, where fits new as_area |
* |
* @param sz Requested size of the allocation. |
* @param size Requested size of the allocation. |
* |
* @return Pointer to the beginning |
* @return pointer to the beginning |
* |
* TODO: make some first_fit/... algorithm, we are now just incrementing |
* the pointer to last area |
*/ |
void *as_get_mappable_page(size_t sz) |
void *as_get_mappable_page(size_t size) |
{ |
void *res; |
uint64_t asz; |
int i; |
if (size == 0) |
return NULL; |
if (!sz) |
return NULL; |
asz = 1 << (fnzb64(sz - 1) + 1); |
/* Set heapsize to some meaningful value */ |
if (maxheapsize == (size_t) -1) |
set_maxheapsize(MAX_HEAP_SIZE); |
size_t sz = 1 << (fnzb(size - 1) + 1); |
if (last_allocated == 0) |
last_allocated = get_max_heap_addr(); |
/* |
* Make sure we allocate from naturally aligned address. |
*/ |
i = 0; |
if (!last_allocated) { |
last_allocated = (void *) ALIGN_UP((void *) &_heap + |
maxheapsize, asz); |
} else { |
last_allocated = (void *) ALIGN_UP(((uintptr_t) |
last_allocated) + (int) (i > 0), asz); |
} |
res = last_allocated; |
last_allocated += ALIGN_UP(sz, PAGE_SIZE); |
return res; |
uintptr_t res = ALIGN_UP(last_allocated, sz); |
last_allocated = res + ALIGN_UP(size, PAGE_SIZE); |
return ((void *) res); |
} |
/** @} |
/branches/dd/uspace/lib/libc/generic/malloc.c |
---|
0,0 → 1,475 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Petr Tuma |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <malloc.h> |
#include <bool.h> |
#include <as.h> |
#include <align.h> |
#include <macros.h> |
#include <assert.h> |
#include <errno.h> |
#include <bitops.h> |
#include <mem.h> |
#include <adt/gcdlcm.h> |
/* Magic used in heap headers. */ |
#define HEAP_BLOCK_HEAD_MAGIC 0xBEEF0101 |
/* Magic used in heap footers. */ |
#define HEAP_BLOCK_FOOT_MAGIC 0xBEEF0202 |
/** Allocation alignment (this also covers the alignment of fields |
in the heap header and footer) */ |
#define BASE_ALIGN 16 |
/** |
* Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures |
*/ |
#define MAX_HEAP_SIZE (sizeof(uintptr_t) << 28) |
/** |
* |
*/ |
#define STRUCT_OVERHEAD (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) |
/** |
* Calculate real size of a heap block (with header and footer) |
*/ |
#define GROSS_SIZE(size) ((size) + STRUCT_OVERHEAD) |
/** |
* Calculate net size of a heap block (without header and footer) |
*/ |
#define NET_SIZE(size) ((size) - STRUCT_OVERHEAD) |
/** Header of a heap block |
* |
*/ |
typedef struct { |
/* Size of the block (including header and footer) */ |
size_t size; |
/* Indication of a free block */ |
bool free; |
/* A magic value to detect overwrite of heap header */ |
uint32_t magic; |
} heap_block_head_t; |
/** Footer of a heap block |
* |
*/ |
typedef struct { |
/* Size of the block (including header and footer) */ |
size_t size; |
/* A magic value to detect overwrite of heap footer */ |
uint32_t magic; |
} heap_block_foot_t; |
/** Linker heap symbol */ |
extern char _heap; |
/** Address of heap start */ |
static void *heap_start = 0; |
/** Address of heap end */ |
static void *heap_end = 0; |
/** Maximum heap size */ |
static size_t max_heap_size = (size_t) -1; |
/** Current number of pages of heap area */ |
static size_t heap_pages = 0; |
/** Initialize a heap block |
* |
* Fills in the structures related to a heap block. |
* |
* @param addr Address of the block. |
* @param size Size of the block including the header and the footer. |
* @param free Indication of a free block. |
* |
*/ |
static void block_init(void *addr, size_t size, bool free) |
{ |
/* Calculate the position of the header and the footer */ |
heap_block_head_t *head = (heap_block_head_t *) addr; |
heap_block_foot_t *foot = |
(heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t)); |
head->size = size; |
head->free = free; |
head->magic = HEAP_BLOCK_HEAD_MAGIC; |
foot->size = size; |
foot->magic = HEAP_BLOCK_FOOT_MAGIC; |
} |
/** Check a heap block |
* |
* Verifies that the structures related to a heap block still contain |
* the magic constants. This helps detect heap corruption early on. |
* |
* @param addr Address of the block. |
* |
*/ |
static void block_check(void *addr) |
{ |
heap_block_head_t *head = (heap_block_head_t *) addr; |
assert(head->magic == HEAP_BLOCK_HEAD_MAGIC); |
heap_block_foot_t *foot = |
(heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t)); |
assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC); |
assert(head->size == foot->size); |
} |
static bool grow_heap(size_t size) |
{ |
if (size == 0) |
return false; |
size_t heap_size = (size_t) (heap_end - heap_start); |
if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size)) |
return false; |
size_t pages = (size - 1) / PAGE_SIZE + 1; |
if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0) |
== EOK) { |
void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) + |
(heap_pages + pages) * PAGE_SIZE, BASE_ALIGN); |
block_init(heap_end, end - heap_end, true); |
heap_pages += pages; |
heap_end = end; |
return true; |
} |
return false; |
} |
static void shrink_heap(void) |
{ |
// TODO |
} |
/** Initialize the heap allocator |
* |
* Finds how much physical memory we have and creates |
* the heap management structures that mark the whole |
* physical memory as a single free block. |
* |
*/ |
void __heap_init(void) |
{ |
if (as_area_create((void *) &_heap, PAGE_SIZE, |
AS_AREA_WRITE | AS_AREA_READ)) { |
heap_pages = 1; |
heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN); |
heap_end = |
(void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN); |
/* Make the entire area one large block. */ |
block_init(heap_start, heap_end - heap_start, true); |
} |
} |
uintptr_t get_max_heap_addr(void) |
{ |
if (max_heap_size == (size_t) -1) |
max_heap_size = |
max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE); |
return ((uintptr_t) heap_start + max_heap_size); |
} |
static void split_mark(heap_block_head_t *cur, const size_t size) |
{ |
assert(cur->size >= size); |
/* See if we should split the block. */ |
size_t split_limit = GROSS_SIZE(size); |
if (cur->size > split_limit) { |
/* Block big enough -> split. */ |
void *next = ((void *) cur) + size; |
block_init(next, cur->size - size, true); |
block_init(cur, size, false); |
} else { |
/* Block too small -> use as is. */ |
cur->free = false; |
} |
} |
/** Allocate a memory block |
* |
* @param size The size of the block to allocate. |
* @param align Memory address alignment. |
* |
* @return the address of the block or NULL when not enough memory. |
* |
*/ |
static void *malloc_internal(const size_t size, const size_t align) |
{ |
if (align == 0) |
return NULL; |
size_t falign = lcm(align, BASE_ALIGN); |
size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); |
bool grown = false; |
void *result; |
loop: |
result = NULL; |
heap_block_head_t *cur = (heap_block_head_t *) heap_start; |
while ((result == NULL) && ((void *) cur < heap_end)) { |
block_check(cur); |
/* Try to find a block that is free and large enough. */ |
if ((cur->free) && (cur->size >= real_size)) { |
/* We have found a suitable block. |
Check for alignment properties. */ |
void *addr = ((void *) cur) + sizeof(heap_block_head_t); |
void *aligned = (void *) ALIGN_UP(addr, falign); |
if (addr == aligned) { |
/* Exact block start including alignment. */ |
split_mark(cur, real_size); |
result = addr; |
} else { |
/* Block start has to be aligned */ |
size_t excess = (size_t) (aligned - addr); |
if (cur->size >= real_size + excess) { |
/* The current block is large enough to fit |
data in including alignment */ |
if ((void *) cur > heap_start) { |
/* There is a block before the current block. |
This previous block can be enlarged to compensate |
for the alignment excess */ |
heap_block_foot_t *prev_foot = |
((void *) cur) - sizeof(heap_block_foot_t); |
heap_block_head_t *prev_head = |
(heap_block_head_t *) (((void *) cur) - prev_foot->size); |
block_check(prev_head); |
size_t reduced_size = cur->size - excess; |
heap_block_head_t *next_head = ((void *) cur) + excess; |
if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) { |
/* The previous block is not free and there is enough |
space to fill in a new free block between the previous |
and current block */ |
block_init(cur, excess, true); |
} else { |
/* The previous block is free (thus there is no need to |
induce additional fragmentation to the heap) or the |
excess is small, thus just enlarge the previous block */ |
block_init(prev_head, prev_head->size + excess, prev_head->free); |
} |
block_init(next_head, reduced_size, true); |
split_mark(next_head, real_size); |
result = aligned; |
cur = next_head; |
} else { |
/* The current block is the first block on the heap. |
We have to make sure that the alignment excess |
is large enough to fit a new free block just |
before the current block */ |
while (excess < STRUCT_OVERHEAD) { |
aligned += falign; |
excess += falign; |
} |
/* Check for current block size again */ |
if (cur->size >= real_size + excess) { |
size_t reduced_size = cur->size - excess; |
cur = (heap_block_head_t *) (heap_start + excess); |
block_init(heap_start, excess, true); |
block_init(cur, reduced_size, true); |
split_mark(cur, real_size); |
result = aligned; |
} |
} |
} |
} |
} |
/* Advance to the next block. */ |
cur = (heap_block_head_t *) (((void *) cur) + cur->size); |
} |
if ((result == NULL) && (!grown)) { |
if (grow_heap(real_size)) { |
grown = true; |
goto loop; |
} |
} |
return result; |
} |
void *malloc(const size_t size) |
{ |
return malloc_internal(size, BASE_ALIGN); |
} |
void *memalign(const size_t align, const size_t size) |
{ |
if (align == 0) |
return NULL; |
size_t palign = |
1 << (fnzb(max(sizeof(void *), align) - 1) + 1); |
return malloc_internal(size, palign); |
} |
void *realloc(const void *addr, const size_t size) |
{ |
if (addr == NULL) |
return malloc(size); |
/* Calculate the position of the header. */ |
heap_block_head_t *head = |
(heap_block_head_t *) (addr - sizeof(heap_block_head_t)); |
assert((void *) head >= heap_start); |
assert((void *) head < heap_end); |
block_check(head); |
assert(!head->free); |
void *ptr = NULL; |
size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN)); |
size_t orig_size = head->size; |
if (orig_size > real_size) { |
/* Shrink */ |
if (orig_size - real_size >= STRUCT_OVERHEAD) { |
/* Split the original block to a full block |
and a tailing free block */ |
block_init((void *) head, real_size, false); |
block_init((void *) head + real_size, |
orig_size - real_size, true); |
shrink_heap(); |
} |
ptr = ((void *) head) + sizeof(heap_block_head_t); |
} else { |
/* Look at the next block. If it is free and the size is |
sufficient then merge the two. */ |
heap_block_head_t *next_head = |
(heap_block_head_t *) (((void *) head) + head->size); |
if (((void *) next_head < heap_end) && |
(head->size + next_head->size >= real_size) && |
(next_head->free)) { |
block_check(next_head); |
block_init(head, head->size + next_head->size, false); |
split_mark(head, ALIGN_UP(size, BASE_ALIGN)); |
ptr = ((void *) head) + sizeof(heap_block_head_t); |
} else { |
ptr = malloc(size); |
if (ptr != NULL) { |
memcpy(ptr, addr, NET_SIZE(orig_size)); |
free(addr); |
} |
} |
} |
return ptr; |
} |
/** Free a memory block |
* |
* @param addr The address of the block. |
*/ |
void free(const void *addr) |
{ |
/* Calculate the position of the header. */ |
heap_block_head_t *head |
= (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); |
assert((void *) head >= heap_start); |
assert((void *) head < heap_end); |
block_check(head); |
assert(!head->free); |
/* Mark the block itself as free. */ |
head->free = true; |
/* Look at the next block. If it is free, merge the two. */ |
heap_block_head_t *next_head |
= (heap_block_head_t *) (((void *) head) + head->size); |
if ((void *) next_head < heap_end) { |
block_check(next_head); |
if (next_head->free) |
block_init(head, head->size + next_head->size, true); |
} |
/* Look at the previous block. If it is free, merge the two. */ |
if ((void *) head > heap_start) { |
heap_block_foot_t *prev_foot = |
(heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t)); |
heap_block_head_t *prev_head = |
(heap_block_head_t *) (((void *) head) - prev_foot->size); |
block_check(prev_head); |
if (prev_head->free) |
block_init(prev_head, prev_head->size + head->size, true); |
} |
shrink_heap(); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/libc.c |
---|
52,11 → 52,8 |
#include <as.h> |
#include <loader/pcb.h> |
extern char _heap; |
extern int main(int argc, char *argv[]); |
int _errno; |
void _exit(int status) |
{ |
thread_exit(status); |
64,9 → 61,10 |
void __main(void *pcb_ptr) |
{ |
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ); |
_async_init(); |
int retval; |
__heap_init(); |
__async_init(); |
fibril_t *fibril = fibril_setup(); |
__tcb_set(fibril->tcb); |
79,15 → 77,17 |
if (__pcb == NULL) { |
argc = 0; |
argv = NULL; |
stdio_init(0, NULL); |
__stdio_init(0, NULL); |
} else { |
argc = __pcb->argc; |
argv = __pcb->argv; |
stdio_init(__pcb->filc, __pcb->filv); |
__stdio_init(__pcb->filc, __pcb->filv); |
} |
main(argc, argv); |
stdio_done(); |
retval = main(argc, argv); |
__stdio_done(); |
(void) task_retval(retval); |
} |
void __exit(void) |
/branches/dd/uspace/lib/libc/generic/devmap.c |
---|
193,7 → 193,7 |
if (retval != EOK) { |
if (handle != NULL) |
*handle = -1; |
*handle = (dev_handle_t) -1; |
return retval; |
} |
218,6 → 218,31 |
return phone; |
} |
int devmap_null_create(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return -1; |
ipcarg_t null_id; |
int retval = async_req_0_1(phone, DEVMAP_DEVICE_NULL_CREATE, &null_id); |
if (retval != EOK) |
return -1; |
return (int) null_id; |
} |
void devmap_null_destroy(int null_id) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
if (phone < 0) |
return; |
async_req_1_0(phone, DEVMAP_DEVICE_NULL_DESTROY, (ipcarg_t) null_id); |
} |
ipcarg_t devmap_device_get_count(void) |
{ |
int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING); |
/branches/dd/uspace/lib/libc/generic/async.c |
---|
178,7 → 178,6 |
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); |
static void default_pending(void); |
/** |
* Pointer to a fibril function that will be used to handle connections. |
191,12 → 190,6 |
*/ |
static async_client_conn_t interrupt_received = default_interrupt_received; |
/** |
* Pointer to a fibril function that will be used to handle pending |
* operations. |
*/ |
static async_pending_t pending = default_pending; |
static hash_table_t conn_hash_table; |
static LIST_INITIALIZE(timeout_list); |
381,42 → 374,6 |
return true; |
} |
/** Pending fibril. |
* |
* After each call the pending operations are executed in a separate |
* fibril. The function pending() is c. |
* |
* @param arg Unused. |
* |
* @return Always zero. |
* |
*/ |
static int pending_fibril(void *arg) |
{ |
pending(); |
return 0; |
} |
/** Process pending actions. |
* |
* A new fibril is created which would process the pending operations. |
* |
* @return False if an error occured. |
* True if the execution was passed to the pending fibril. |
* |
*/ |
static bool process_pending(void) |
{ |
futex_down(&async_futex); |
fid_t fid = fibril_create(pending_fibril, NULL); |
fibril_add_ready(fid); |
futex_up(&async_futex); |
return true; |
} |
/** Return new incoming message for the current (fibril-local) connection. |
* |
* @param call Storage where the incoming call data will be stored. |
513,15 → 470,6 |
{ |
} |
/** Default fibril function that gets called to handle pending operations. |
* |
* This function is defined as a weak symbol - to be redefined in user code. |
* |
*/ |
static void default_pending(void) |
{ |
} |
/** Wrapper for client connection fibril. |
* |
* When a new connection arrives, a fibril with this implementing function is |
660,7 → 608,7 |
return; |
out: |
process_pending(); |
; |
} |
/** Fire all timeouts that expired. */ |
790,7 → 738,7 |
* |
* @return Zero on success or an error code. |
*/ |
int _async_init(void) |
int __async_init(void) |
{ |
if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, |
&conn_hash_table_ops)) { |
1049,16 → 997,6 |
interrupt_received = intr; |
} |
/** Setter for pending function pointer. |
* |
* @param pend Function that will implement a new pending |
* operations fibril. |
*/ |
void async_set_pending(async_pending_t pend) |
{ |
pending = pend; |
} |
/** Pseudo-synchronous message sending - fast version. |
* |
* Send message asynchronously and return only after the reply arrives. |
/branches/dd/uspace/lib/libc/generic/vfs/vfs.c |
---|
38,8 → 38,8 |
#include <unistd.h> |
#include <dirent.h> |
#include <fcntl.h> |
#include <stdio.h> |
#include <sys/stat.h> |
#include <stdio.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
137,7 → 137,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL); |
req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
198,7 → 198,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer); |
req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
230,7 → 230,7 |
vfs_connect(); |
ipc_call_t answer; |
aid_t req = async_send_4(vfs_phone, VFS_OPEN_NODE, node->fs_handle, |
aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle, |
node->dev_handle, node->index, oflag, &answer); |
ipcarg_t rc; |
252,7 → 252,7 |
async_serialize_start(); |
vfs_connect(); |
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes); |
rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
270,7 → 270,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer); |
req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer); |
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
297,7 → 297,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer); |
req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer); |
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
314,95 → 314,116 |
return -1; |
} |
int fd_phone(int fildes) |
int fsync(int fildes) |
{ |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t device; |
ipcarg_t rc = async_req_1_1(vfs_phone, VFS_DEVICE, fildes, &device); |
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return -1; |
return devmap_device_connect((dev_handle_t) device, 0); |
return (int) rc; |
} |
int fd_node(int fildes, fdi_node_t *node) |
off_t lseek(int fildes, off_t offset, int whence) |
{ |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t fs_handle; |
ipcarg_t dev_handle; |
ipcarg_t index; |
ipcarg_t rc = async_req_1_3(vfs_phone, VFS_NODE, fildes, &fs_handle, |
&dev_handle, &index); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence, |
&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return (off_t) -1; |
if (rc == EOK) { |
node->fs_handle = (fs_handle_t) fs_handle; |
node->dev_handle = (dev_handle_t) dev_handle; |
node->index = (fs_index_t) index; |
} |
return rc; |
return (off_t) newoffs; |
} |
int fsync(int fildes) |
int ftruncate(int fildes, off_t length) |
{ |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_SYNC, fildes); |
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
} |
off_t lseek(int fildes, off_t offset, int whence) |
int fstat(int fildes, struct stat *stat) |
{ |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
&newoffs); |
req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL); |
rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (ssize_t) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
if (rc != EOK) |
return (off_t) -1; |
return (off_t) newoffs; |
return rc; |
} |
int ftruncate(int fildes, off_t length) |
int stat(const char *path, struct stat *stat) |
{ |
ipcarg_t rc; |
aid_t req; |
size_t pa_size; |
char *pa = absolutize(path, &pa_size); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
vfs_connect(); |
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length); |
req = async_send_0(vfs_phone, VFS_IN_STAT, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return (int) rc; |
free(pa); |
return rc; |
} |
DIR *opendir(const char *dirname) |
452,7 → 473,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL); |
req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
482,7 → 503,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_UNLINK, NULL); |
req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
529,7 → 550,7 |
async_serialize_start(); |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_RENAME, NULL); |
req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
598,5 → 619,34 |
return buf; |
} |
int fd_phone(int fildes) |
{ |
struct stat stat; |
int rc; |
rc = fstat(fildes, &stat); |
if (!stat.devfs_stat.device) |
return -1; |
return devmap_device_connect(stat.devfs_stat.device, 0); |
} |
int fd_node(int fildes, fdi_node_t *node) |
{ |
struct stat stat; |
int rc; |
rc = fstat(fildes, &stat); |
if (rc == EOK) { |
node->fs_handle = stat.fs_handle; |
node->dev_handle = stat.dev_handle; |
node->index = stat.index; |
} |
return rc; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/errno.c |
---|
0,0 → 1,41 |
/* |
* Copyright (c) 2009 Martin Decky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <errno.h> |
#include <fibril.h> |
int _errno; |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/console.c |
---|
69,6 → 69,17 |
async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false); |
} |
int console_get_color_cap(int phone, int *ccap) |
{ |
ipcarg_t ccap_tmp; |
int rc; |
rc = async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, &ccap_tmp); |
*ccap = ccap_tmp; |
return rc; |
} |
void console_kcon_enable(int phone) |
{ |
async_msg_0(phone, CONSOLE_KCON_ENABLE); |
/branches/dd/uspace/lib/libc/generic/io/io.c |
---|
35,6 → 35,7 |
#include <stdio.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <assert.h> |
#include <string.h> |
#include <errno.h> |
#include <bool.h> |
44,12 → 45,18 |
#include <ipc/devmap.h> |
#include <adt/list.h> |
static void _fflushbuf(FILE *stream); |
static FILE stdin_null = { |
.fd = -1, |
.error = true, |
.eof = true, |
.klog = false, |
.phone = -1 |
.phone = -1, |
.btype = _IONBF, |
.buf = NULL, |
.buf_size = 0, |
.buf_head = NULL |
}; |
static FILE stdout_klog = { |
57,7 → 64,11 |
.error = false, |
.eof = false, |
.klog = true, |
.phone = -1 |
.phone = -1, |
.btype = _IOLBF, |
.buf = NULL, |
.buf_size = BUFSIZ, |
.buf_head = NULL |
}; |
static FILE stderr_klog = { |
65,7 → 76,11 |
.error = false, |
.eof = false, |
.klog = true, |
.phone = -1 |
.phone = -1, |
.btype = _IONBF, |
.buf = NULL, |
.buf_size = 0, |
.buf_head = NULL |
}; |
FILE *stdin = NULL; |
74,7 → 89,7 |
static LIST_INITIALIZE(files); |
void stdio_init(int filc, fdi_node_t *filv[]) |
void __stdio_init(int filc, fdi_node_t *filv[]) |
{ |
if (filc > 0) { |
stdin = fopen_node(filv[0], "r"); |
98,7 → 113,7 |
} |
} |
void stdio_done(void) |
void __stdio_done(void) |
{ |
link_t *link = files.next; |
156,6 → 171,47 |
return true; |
} |
/** Set stream buffer. */ |
void setvbuf(FILE *stream, void *buf, int mode, size_t size) |
{ |
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. */ |
switch (stream->fd) { |
case 1: |
setvbuf(stream, NULL, _IOLBF, BUFSIZ); |
break; |
case 0: |
case 2: |
setvbuf(stream, NULL, _IONBF, 0); |
break; |
default: |
setvbuf(stream, NULL, _IOFBF, BUFSIZ); |
} |
} |
/** Allocate stream buffer. */ |
static int _fallocbuf(FILE *stream) |
{ |
assert(stream->buf == NULL); |
stream->buf = malloc(stream->buf_size); |
if (stream->buf == NULL) { |
errno = ENOMEM; |
return -1; |
} |
stream->buf_head = stream->buf; |
return 0; |
} |
/** Open a stream. |
* |
* @param path Path of the file to open. |
186,6 → 242,7 |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
list_append(&stream->link, &files); |
206,6 → 263,7 |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
list_append(&stream->link, &files); |
236,6 → 294,7 |
stream->eof = false; |
stream->klog = false; |
stream->phone = -1; |
_setvbuf(stream); |
list_append(&stream->link, &files); |
284,6 → 343,9 |
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); |
300,15 → 362,7 |
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 stream Pointer to the stream. |
* |
*/ |
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) |
static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) |
{ |
size_t left = size * nmemb; |
size_t done = 0; |
332,6 → 386,93 |
return (done / size); |
} |
/** Drain stream buffer, do not sync stream. */ |
static void _fflushbuf(FILE *stream) |
{ |
size_t bytes_used; |
if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error)) |
return; |
bytes_used = stream->buf_head - stream->buf; |
if (bytes_used == 0) |
return; |
(void) _fwrite(stream->buf, 1, bytes_used, stream); |
stream->buf_head = stream->buf; |
} |
/** Write to a stream. |
* |
* @param buf Source buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to write. |
* @param stream Pointer to the stream. |
* |
*/ |
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) |
{ |
uint8_t *data; |
size_t bytes_left; |
size_t now; |
size_t buf_free; |
size_t total_written; |
size_t i; |
uint8_t b; |
bool need_flush; |
/* If not buffered stream, write out directly. */ |
if (stream->btype == _IONBF) { |
now = _fwrite(buf, size, nmemb, stream); |
fflush(stream); |
return now; |
} |
/* Perform lazy allocation of stream buffer. */ |
if (stream->buf == NULL) { |
if (_fallocbuf(stream) != 0) |
return 0; /* Errno set by _fallocbuf(). */ |
} |
data = (uint8_t *) buf; |
bytes_left = size * nmemb; |
total_written = 0; |
need_flush = false; |
while ((!stream->error) && (bytes_left > 0)) { |
buf_free = stream->buf_size - (stream->buf_head - stream->buf); |
if (bytes_left > buf_free) |
now = buf_free; |
else |
now = bytes_left; |
for (i = 0; i < now; i++) { |
b = data[i]; |
stream->buf_head[i] = b; |
if ((b == '\n') && (stream->btype == _IOLBF)) |
need_flush = true; |
} |
buf += now; |
stream->buf_head += now; |
buf_free -= now; |
bytes_left -= now; |
total_written += now; |
if (buf_free == 0) { |
/* Only need to drain buffer. */ |
_fflushbuf(stream); |
need_flush = false; |
} |
} |
if (need_flush) |
fflush(stream); |
return (total_written / size); |
} |
int fputc(wchar_t c, FILE *stream) |
{ |
char buf[STR_BOUNDS(1)]; |
367,13 → 508,13 |
int fgetc(FILE *stream) |
{ |
char c; |
/* This could be made faster by only flushing when needed. */ |
if (stdout) |
fflush(stdout); |
if (stderr) |
fflush(stderr); |
if (fread(&c, sizeof(char), 1, stream) < sizeof(char)) |
return EOF; |
405,6 → 546,8 |
int fflush(FILE *stream) |
{ |
_fflushbuf(stream); |
if (stream->klog) { |
klog_update(); |
return EOK; |
/branches/dd/uspace/lib/libc/generic/io/printf_core.c |
---|
301,9 → 301,6 |
if (str == NULL) |
return printf_putstr(nullstr, ps); |
if (*str == U_BOM) |
str++; |
/* Print leading spaces. */ |
size_t strw = wstr_length(str); |
if (precision == 0) |
/branches/dd/uspace/lib/libc/generic/mman.c |
---|
37,17 → 37,18 |
#include <as.h> |
#include <unistd.h> |
void *mmap(void *start, size_t length, int prot, int flags, int fd, |
void *mmap(void *start, size_t length, int prot, int flags, int fd, |
off_t offset) |
{ |
if (!start) |
start = as_get_mappable_page(length); |
// if (! ((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE))) |
// if (!((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE))) |
// return MAP_FAILED; |
if (! (flags & MAP_ANONYMOUS)) |
if (!(flags & MAP_ANONYMOUS)) |
return MAP_FAILED; |
return as_area_create(start, length, prot); |
} |
/branches/dd/uspace/lib/libc/Makefile |
---|
32,6 → 32,7 |
LIBC_PREFIX = $(shell pwd) |
SOFTINT_PREFIX = ../softint |
## Setup toolchain |
# |
48,6 → 49,7 |
generic/cap.c \ |
generic/devmap.c \ |
generic/event.c \ |
generic/errno.c \ |
generic/mem.c \ |
generic/string.c \ |
generic/fibril.c \ |
67,7 → 69,7 |
generic/io/vsnprintf.c \ |
generic/io/printf_core.c \ |
generic/io/console.c \ |
malloc/malloc.c \ |
generic/malloc.c \ |
generic/sysinfo.c \ |
generic/ipc.c \ |
generic/async.c \ |
104,7 → 106,7 |
clean: |
-rm -f include/kernel include/arch include/libarch libc.a arch/$(UARCH)/_link.ld Makefile.depend |
find generic/ arch/$(UARCH)/ malloc -name '*.o' -follow -exec rm \{\} \; |
find generic/ arch/$(UARCH)/ -name '*.o' -follow -exec rm \{\} \; |
depend: kerninc |
-makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
/branches/dd/uspace/lib/libc/arch/sparc64/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/sparc64/include/stack.h |
---|
45,6 → 45,11 |
*/ |
#define STACK_WINDOW_SAVE_AREA_SIZE (16 * STACK_ITEM_SIZE) |
/* |
* Six extended words for first six arguments. |
*/ |
#define STACK_ARG_SAVE_AREA_SIZE (6 * STACK_ITEM_SIZE) |
/** |
* By convention, the actual top of the stack is %sp + STACK_BIAS. |
*/ |
/branches/dd/uspace/lib/libc/arch/sparc64/include/fibril.h |
---|
39,7 → 39,7 |
#include <sys/types.h> |
#include <align.h> |
#define SP_DELTA STACK_WINDOW_SAVE_AREA_SIZE |
#define SP_DELTA (STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE) |
#ifdef context_set |
#undef context_set |
/branches/dd/uspace/lib/libc/arch/sparc64/Makefile.inc |
---|
38,5 → 38,7 |
CFLAGS += -mcpu=ultrasparc -m64 |
LFLAGS += -no-check-sections -N |
ENDIANESS = BE |
BFD_NAME = elf64-sparc |
BFD_ARCH = sparc |
/branches/dd/uspace/lib/libc/arch/ia64/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ia64/Makefile.inc |
---|
31,9 → 31,6 |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin |
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16 |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \ |
arch/$(UARCH)/src/fibril.S \ |
40,5 → 37,10 |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/ddi.c |
CFLAGS += -fno-unwind-tables |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
ENDIANESS = LE |
BFD_NAME = elf64-ia64-little |
BFD_ARCH = ia64-elf64 |
/branches/dd/uspace/lib/libc/arch/arm32/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/arm32/Makefile.inc |
---|
32,9 → 32,6 |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin |
CFLAGS += -ffixed-r9 -mtp=soft |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
AFLAGS += |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
41,5 → 38,10 |
arch/$(UARCH)/src/tls.c \ |
arch/$(UARCH)/src/eabi.S |
CFLAGS += -ffixed-r9 -mtp=soft |
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a |
ENDIANESS = LE |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
/branches/dd/uspace/lib/libc/arch/mips32eb/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/mips32eb/Makefile.inc |
---|
31,13 → 31,15 |
TARGET = mips-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin |
CFLAGS += -mips3 |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mips3 |
LFLAGS += -N |
ENDIANESS = BE |
BFD_ARCH = mips |
BFD_NAME = elf32-tradbigmips |
/branches/dd/uspace/lib/libc/arch/ppc32/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ppc32/Makefile.inc |
---|
40,5 → 40,7 |
AFLAGS += -a32 |
LFLAGS += -N |
ENDIANESS = BE |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
/branches/dd/uspace/lib/libc/arch/amd64/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/amd64/Makefile.inc |
---|
38,5 → 38,7 |
LFLAGS += -N |
ENDIANESS = LE |
BFD_NAME = elf64-x86-64 |
BFD_ARCH = i386:x86-64 |
/branches/dd/uspace/lib/libc/arch/mips32/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/mips32/Makefile.inc |
---|
31,11 → 31,14 |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin |
CFLAGS += -mips3 |
ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \ |
arch/$(UARCH)/src/fibril.S \ |
arch/$(UARCH)/src/tls.c |
CFLAGS += -mips3 |
ENDIANESS = LE |
BFD_ARCH = mips |
BFD_NAME = elf32-tradlittlemips |
/branches/dd/uspace/lib/libc/arch/ia32/include/byteorder.h |
---|
File deleted |
/branches/dd/uspace/lib/libc/arch/ia32/Makefile.inc |
---|
39,5 → 39,7 |
LFLAGS += -N |
ENDIANESS = LE |
BFD_NAME = elf32-i386 |
BFD_ARCH = i386 |
/branches/dd/uspace/srv/kbd/ctl/pc.c |
---|
207,6 → 207,9 |
map = scanmap_e0; |
map_length = sizeof(scanmap_e0) / sizeof(int); |
break; |
default: |
map = NULL; |
map_length = 0; |
} |
ds = ds_s; |
218,7 → 221,7 |
type = KEY_PRESS; |
} |
if (scancode < 0 || scancode >= map_length) |
if ((scancode < 0) || ((size_t) scancode >= map_length)) |
return; |
key = map[scancode]; |
/branches/dd/uspace/srv/kbd/port/i8042.c |
---|
135,8 → 135,8 |
(void) pio_read_8(&i8042->data); |
/* Enable kbd */ |
i8042_kbd.cmds[0].addr = &((i8042_t *) i8042_kernel)->status; |
i8042_kbd.cmds[3].addr = &((i8042_t *) i8042_kernel)->data; |
i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status; |
i8042_kbd.cmds[3].addr = (void *) &((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/dd/uspace/srv/kbd/genarch/gsp.c |
---|
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,7 → 276,8 |
gsp_trans_t *t; |
t = hash_table_get_instance(item, gsp_trans_t, link); |
return (key[0] == t->old_state && key[1] == t->input); |
return ((key[0] == (unsigned long) t->old_state) |
&& (key[1] == (unsigned long) t->input)); |
} |
static void trans_op_remove_callback(link_t *item) |
/branches/dd/uspace/srv/kbd/layout/us_qwerty.c |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @brief US QWERTY layout. |
* @{ |
*/ |
/branches/dd/uspace/srv/kbd/layout/cz.c |
---|
27,7 → 27,7 |
*/ |
/** @addtogroup kbd |
* @brief US QWERTY leyout. |
* @brief Czech QWERTZ layout. |
* @{ |
*/ |
399,6 → 399,8 |
case ms_carka: |
return parse_ms_carka(ev); |
} |
return 0; |
} |
/** |
/branches/dd/uspace/srv/ns/ns.c |
---|
108,13 → 108,6 |
task_id_t id; |
ipcarg_t retval; |
if (callid & IPC_CALLID_NOTIFICATION) { |
id = (task_id_t) |
MERGE_LOUP32(IPC_GET_ARG2(call), IPC_GET_ARG3(call)); |
wait_notification((wait_type_t) IPC_GET_ARG1(call), id); |
continue; |
} |
switch (IPC_GET_METHOD(call)) { |
case IPC_M_SHARE_IN: |
switch (IPC_GET_ARG3(call)) { |
133,7 → 126,7 |
} |
continue; |
case IPC_M_PHONE_HUNGUP: |
retval = EOK; |
retval = ns_task_disconnect(&call); |
break; |
case IPC_M_CONNECT_TO_ME: |
/* |
170,6 → 163,12 |
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; |
/branches/dd/uspace/srv/ns/task.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2009 Martin Decky |
* Copyright (c) 2009 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
41,20 → 42,13 |
#include "ns.h" |
#define TASK_HASH_TABLE_CHAINS 256 |
#define P2I_HASH_TABLE_CHAINS 256 |
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id); |
/* TODO: |
* |
* The current implementation of waiting on a task is not perfect. If somebody |
* wants to wait on a task which has already finished before the NS asked |
* the kernel to receive notifications, it would block indefinitively. |
* |
* A solution to this is to fail immediately on a task for which no creation |
* notification was received yet. However, there is a danger of a race condition |
* in this solution -- the caller has to make sure that it is not trying to wait |
* before the NS has a change to receive the task creation notification. This |
* can be assured by waiting for this event in task_spawn(). |
* |
* Finally, as there is currently no convention that each task has to be waited |
* As there is currently no convention that each task has to be waited |
* for, the NS can leak memory because of the zombie tasks. |
* |
*/ |
62,8 → 56,10 |
/** Task hash table item. */ |
typedef struct { |
link_t link; |
task_id_t id; /**< Task ID. */ |
bool destroyed; |
task_id_t id; /**< Task ID. */ |
bool finished; /**< Task is done. */ |
bool have_rval; /**< Task returned a value. */ |
int retval; /**< The return value. */ |
} hashed_task_t; |
/** Compute hash index into task hash table. |
83,7 → 79,7 |
/** Compare a key with hashed item. |
* |
* @param key Array of keys. |
* @param keys Must be lesser or equal to 2. |
* @param keys Must be less than or equal to 2. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
125,6 → 121,65 |
/** Task hash table structure. */ |
static hash_table_t task_hash_table; |
typedef struct { |
link_t link; |
ipcarg_t phash; /**< Task ID. */ |
task_id_t id; /**< Task ID. */ |
} p2i_entry_t; |
/** Compute hash index into task hash table. |
* |
* @param key Array of keys. |
* @return Hash index corresponding to key[0]. |
* |
*/ |
static hash_index_t p2i_hash(unsigned long *key) |
{ |
assert(key); |
return (*key % TASK_HASH_TABLE_CHAINS); |
} |
/** Compare a key with hashed item. |
* |
* @param key Array of keys. |
* @param keys Must be less than or equal to 1. |
* @param item Pointer to a hash table item. |
* |
* @return Non-zero if the key matches the item, zero otherwise. |
* |
*/ |
static int p2i_compare(unsigned long key[], hash_count_t keys, link_t *item) |
{ |
assert(key); |
assert(keys == 1); |
assert(item); |
p2i_entry_t *e = hash_table_get_instance(item, p2i_entry_t, link); |
return (key[0] == e->phash); |
} |
/** Perform actions after removal of item from the hash table. |
* |
* @param item Item that was removed from the hash table. |
* |
*/ |
static void p2i_remove(link_t *item) |
{ |
assert(item); |
free(hash_table_get_instance(item, p2i_entry_t, link)); |
} |
/** Operations for task hash table. */ |
static hash_table_operations_t p2i_ops = { |
.hash = p2i_hash, |
.compare = p2i_compare, |
.remove_callback = p2i_remove |
}; |
/** Map phone hash to task ID */ |
static hash_table_t phone_to_id; |
/** Pending task wait structure. */ |
typedef struct { |
link_t link; |
141,10 → 196,13 |
printf(NAME ": No memory available for tasks\n"); |
return ENOMEM; |
} |
if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS, |
1, &p2i_ops)) { |
printf(NAME ": No memory available for tasks\n"); |
return ENOMEM; |
} |
if (event_subscribe(EVENT_WAIT, 0) != EOK) |
printf(NAME ": Error registering wait notifications\n"); |
list_initialize(&pending_wait); |
return EOK; |
154,6 → 212,7 |
void process_pending_wait(void) |
{ |
link_t *cur; |
task_exit_t texit; |
loop: |
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) { |
169,12 → 228,16 |
continue; |
hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link); |
if (!ht->destroyed) |
if (!ht->finished) |
continue; |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(pr->callid, EOK); |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) { |
texit = ht->have_rval ? TASK_EXIT_NORMAL : |
TASK_EXIT_UNEXPECTED; |
ipc_answer_2(pr->callid, EOK, texit, |
ht->retval); |
} |
hash_table_remove(&task_hash_table, keys, 2); |
list_remove(cur); |
free(pr); |
182,66 → 245,27 |
} |
} |
static void fail_pending_wait(task_id_t id, int rc) |
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid) |
{ |
link_t *cur; |
loop: |
for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) { |
pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link); |
if (pr->id == id) { |
if (!(pr->callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(pr->callid, rc); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
} |
ipcarg_t retval; |
task_exit_t texit; |
void wait_notification(wait_type_t et, task_id_t id) |
{ |
unsigned long keys[2] = { |
LOWER32(id), |
UPPER32(id) |
}; |
link_t *link = hash_table_find(&task_hash_table, keys); |
if (link == NULL) { |
hashed_task_t *ht = |
(hashed_task_t *) malloc(sizeof(hashed_task_t)); |
if (ht == NULL) { |
fail_pending_wait(id, ENOMEM); |
return; |
} |
link_initialize(&ht->link); |
ht->id = id; |
ht->destroyed = (et == TASK_CREATE) ? false : true; |
hash_table_insert(&task_hash_table, keys, &ht->link); |
} else { |
hashed_task_t *ht = |
hash_table_get_instance(link, hashed_task_t, link); |
ht->destroyed = (et == TASK_CREATE) ? false : true; |
} |
} |
void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid) |
{ |
ipcarg_t retval; |
unsigned long keys[2] = { |
LOWER32(id), |
UPPER32(id) |
}; |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if ((ht == NULL) || (!ht->destroyed)) { |
if (ht == NULL) { |
/* No such task exists. */ |
retval = ENOENT; |
goto out; |
} |
if (!ht->finished) { |
/* Add to pending list */ |
pending_wait_t *pr = |
(pending_wait_t *) malloc(sizeof(pending_wait_t)); |
260,10 → 284,131 |
retval = EOK; |
out: |
if (!(callid & IPC_CALLID_NOTIFICATION)) |
ipc_answer_0(callid, retval); |
if (!(callid & IPC_CALLID_NOTIFICATION)) { |
texit = ht->have_rval ? TASK_EXIT_NORMAL : TASK_EXIT_UNEXPECTED; |
ipc_answer_2(callid, retval, texit, ht->retval); |
} |
} |
int ns_task_id_intro(ipc_call_t *call) |
{ |
task_id_t id; |
unsigned long keys[2]; |
link_t *link; |
p2i_entry_t *e; |
hashed_task_t *ht; |
id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call)); |
keys[0] = call->in_phone_hash; |
link = hash_table_find(&phone_to_id, keys); |
if (link != NULL) |
return EEXISTS; |
e = (p2i_entry_t *) malloc(sizeof(p2i_entry_t)); |
if (e == NULL) |
return ENOMEM; |
ht = (hashed_task_t *) malloc(sizeof(hashed_task_t)); |
if (ht == NULL) |
return ENOMEM; |
/* Insert to phone-to-id map. */ |
link_initialize(&e->link); |
e->phash = call->in_phone_hash; |
e->id = id; |
hash_table_insert(&phone_to_id, keys, &e->link); |
/* Insert to main table. */ |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_initialize(&ht->link); |
ht->id = id; |
ht->finished = false; |
ht->have_rval = false; |
ht->retval = -1; |
hash_table_insert(&task_hash_table, keys, &ht->link); |
return EOK; |
} |
int ns_task_retval(ipc_call_t *call) |
{ |
task_id_t id; |
unsigned long keys[2]; |
int rc; |
rc = get_id_by_phone(call->in_phone_hash, &id); |
if (rc != EOK) |
return rc; |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = (link != NULL) ? |
hash_table_get_instance(link, hashed_task_t, link) : NULL; |
if ((ht == NULL) || ht->finished) |
return EINVAL; |
ht->finished = true; |
ht->have_rval = true; |
ht->retval = IPC_GET_ARG1(*call); |
return EOK; |
} |
int ns_task_disconnect(ipc_call_t *call) |
{ |
unsigned long keys[2]; |
task_id_t id; |
int rc; |
rc = get_id_by_phone(call->in_phone_hash, &id); |
if (rc != EOK) |
return rc; |
/* Delete from phone-to-id map. */ |
keys[0] = call->in_phone_hash; |
hash_table_remove(&phone_to_id, keys, 1); |
/* Mark task as finished. */ |
keys[0] = LOWER32(id); |
keys[1] = UPPER32(id); |
link_t *link = hash_table_find(&task_hash_table, keys); |
hashed_task_t *ht = |
hash_table_get_instance(link, hashed_task_t, link); |
if (ht == NULL) |
return EOK; |
ht->finished = true; |
return EOK; |
} |
static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id) |
{ |
unsigned long keys[1]; |
link_t *link; |
p2i_entry_t *e; |
keys[0] = phone_hash; |
link = hash_table_find(&phone_to_id, keys); |
if (link == NULL) |
return ENOENT; |
e = hash_table_get_instance(link, p2i_entry_t, link); |
*id = e->id; |
return EOK; |
} |
/** |
* @} |
*/ |
/branches/dd/uspace/srv/ns/task.h |
---|
42,6 → 42,11 |
extern void wait_notification(wait_type_t et, task_id_t id); |
extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid); |
extern int ns_task_id_intro(ipc_call_t *call); |
extern int ns_task_disconnect(ipc_call_t *call); |
extern int ns_task_retval(ipc_call_t *call); |
#endif |
/** |
/branches/dd/uspace/srv/console/screenbuffer.h |
---|
135,6 → 135,8 |
return (a1.a.r.fg_color == a2.a.r.fg_color) |
&& (a1.a.r.bg_color == a2.a.r.bg_color); |
} |
return 0; |
} |
/branches/dd/uspace/srv/console/console.c |
---|
51,6 → 51,7 |
#include <sysinfo.h> |
#include <event.h> |
#include <devmap.h> |
#include <fibril_sync.h> |
#include "console.h" |
#include "gcons.h" |
68,6 → 69,7 |
int phone; /**< Framebuffer phone */ |
ipcarg_t cols; /**< Framebuffer columns */ |
ipcarg_t rows; /**< Framebuffer rows */ |
int color_cap; /**< Color capabilities (FB_CCAP_xxx) */ |
} fb_info; |
typedef struct { |
97,64 → 99,9 |
size_t cnt; /**< Width of the span. */ |
} fb_pending; |
/** Pending input structure. */ |
typedef struct { |
link_t link; |
console_t *cons; /**< Console waiting for input */ |
ipc_callid_t rid; /**< Call ID waiting for input */ |
ipc_callid_t callid; /**< Call ID waiting for IPC_DATA_READ */ |
size_t pos; /**< Position of the last stored data */ |
size_t size; /**< Size of ther buffer */ |
char *data; /**< Already stored data */ |
} pending_input_t; |
static FIBRIL_MUTEX_INITIALIZE(input_mutex); |
static FIBRIL_CONDVAR_INITIALIZE(input_cv); |
LIST_INITIALIZE(pending_input); |
/** Process pending input requests */ |
static void process_pending_input(void) |
{ |
async_serialize_start(); |
link_t *cur; |
loop: |
for (cur = pending_input.next; cur != &pending_input; cur = cur->next) { |
pending_input_t *pr = list_get_instance(cur, pending_input_t, link); |
console_event_t ev; |
if (keybuffer_pop(&pr->cons->keybuffer, &ev)) { |
if (pr->data != NULL) { |
if (ev.type == KEY_PRESS) { |
pr->data[pr->pos] = ev.c; |
pr->pos++; |
} |
} else { |
ipc_answer_4(pr->rid, EOK, ev.type, ev.key, ev.mods, ev.c); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
if ((pr->data != NULL) && (pr->pos == pr->size)) { |
(void) ipc_data_read_finalize(pr->callid, pr->data, pr->size); |
ipc_answer_1(pr->rid, EOK, pr->size); |
free(pr->data); |
list_remove(cur); |
free(pr); |
goto loop; |
} |
} |
async_serialize_end(); |
} |
static void curs_visibility(bool visible) |
{ |
async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); |
226,6 → 173,19 |
} |
} |
int ccap_fb_to_con(int ccap_fb, int *ccap_con) |
{ |
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; |
} |
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) |
{ |
287,9 → 247,12 |
/** Process a character from the client (TTY emulation). */ |
static void write_char(console_t *cons, wchar_t ch) |
{ |
bool flush_cursor = false; |
switch (ch) { |
case '\n': |
fb_pending_flush(); |
flush_cursor = true; |
cons->scr.position_y++; |
cons->scr.position_x = 0; |
break; |
315,8 → 278,10 |
cons->scr.position_x++; |
} |
if (cons->scr.position_x >= cons->scr.size_x) |
if (cons->scr.position_x >= cons->scr.size_x) { |
flush_cursor = true; |
cons->scr.position_y++; |
} |
if (cons->scr.position_y >= cons->scr.size_y) { |
fb_pending_flush(); |
327,7 → 292,9 |
if (cons == 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; |
} |
446,7 → 413,10 |
break; |
} |
fibril_mutex_lock(&input_mutex); |
keybuffer_push(&active_console->keybuffer, &ev); |
fibril_condvar_broadcast(&input_cv); |
fibril_mutex_unlock(&input_mutex); |
break; |
default: |
retval = ENOENT; |
482,9 → 452,6 |
write_char(cons, ch); |
} |
if (cons == active_console) |
curs_goto(cons->scr.position_x, cons->scr.position_y); |
async_serialize_end(); |
gcons_notify_char(cons->index); |
510,10 → 477,10 |
return; |
} |
async_serialize_start(); |
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; |
526,50 → 493,25 |
ipc_answer_1(rid, EOK, size); |
free(buf); |
} else { |
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t)); |
if (!pr) { |
ipc_answer_0(callid, ENOMEM); |
ipc_answer_0(rid, ENOMEM); |
free(buf); |
async_serialize_end(); |
return; |
} |
pr->cons = cons; |
pr->rid = rid; |
pr->callid = callid; |
pr->pos = pos; |
pr->size = size; |
pr->data = buf; |
list_append(&pr->link, &pending_input); |
fibril_condvar_wait(&input_cv, &input_mutex); |
goto recheck; |
} |
async_serialize_end(); |
fibril_mutex_unlock(&input_mutex); |
} |
static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) |
{ |
async_serialize_start(); |
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 { |
pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t)); |
if (!pr) { |
ipc_answer_0(rid, ENOMEM); |
async_serialize_end(); |
return; |
} |
pr->cons = cons; |
pr->rid = rid; |
pr->callid = 0; |
pr->data = NULL; |
list_append(&pr->link, &pending_input); |
fibril_condvar_wait(&input_cv, &input_mutex); |
goto recheck; |
} |
async_serialize_end(); |
fibril_mutex_unlock(&input_mutex); |
} |
/** Default thread for new connections */ |
598,6 → 540,9 |
ipcarg_t arg1; |
ipcarg_t arg2; |
ipcarg_t arg3; |
int cons_ccap; |
int rc; |
async_serialize_start(); |
if (cons->refcount == 0) |
623,17 → 568,17 |
if (cons->refcount == 0) |
gcons_notify_disconnect(cons->index); |
return; |
case VFS_READ: |
case VFS_OUT_READ: |
async_serialize_end(); |
cons_read(cons, callid, &call); |
async_serialize_start(); |
continue; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
async_serialize_end(); |
cons_write(cons, callid, &call); |
async_serialize_start(); |
continue; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
fb_pending_flush(); |
if (cons == active_console) { |
async_req_0_0(fb_info.phone, FB_FLUSH); |
660,6 → 605,14 |
arg1 = fb_info.cols; |
arg2 = fb_info.rows; |
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; |
} |
arg1 = cons_ccap; |
break; |
case CONSOLE_SET_STYLE: |
fb_pending_flush(); |
arg1 = IPC_GET_ARG1(call); |
711,13 → 664,12 |
static bool console_init(void) |
{ |
async_serialize_start(); |
ipcarg_t color_cap; |
/* 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"); |
async_serialize_end(); |
return false; |
} |
724,18 → 676,15 |
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"); |
async_serialize_end(); |
return false; |
} |
async_set_pending(process_pending_input); |
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) { |
printf(NAME ": Failed to connect to video service\n"); |
async_serialize_end(); |
return -1; |
} |
743,7 → 692,6 |
int rc = devmap_driver_register(NAME, client_connection); |
if (rc < 0) { |
printf(NAME ": Unable to register driver (%d)\n", rc); |
async_serialize_end(); |
return false; |
} |
753,6 → 701,8 |
/* Synchronize, the gcons could put 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; |
/* Set up shared memory buffer. */ |
size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows; |
779,7 → 729,6 |
if (screenbuffer_init(&consoles[i].scr, |
fb_info.cols, fb_info.rows) == NULL) { |
printf(NAME ": Unable to allocate screen buffer %u\n", i); |
async_serialize_end(); |
return false; |
} |
screenbuffer_clear(&consoles[i].scr); |
793,7 → 742,6 |
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s\n", vc); |
async_serialize_end(); |
return false; |
} |
} |
803,11 → 751,13 |
__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) |
815,7 → 765,6 |
async_set_interrupt_received(interrupt_received); |
async_serialize_end(); |
return true; |
} |
/branches/dd/uspace/srv/bd/file_bd/file_bd.c |
---|
44,11 → 44,12 |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <bool.h> |
#include <task.h> |
#define NAME "file_bd" |
56,12 → 57,12 |
static FILE *img; |
static dev_handle_t dev_handle; |
static atomic_t dev_futex = FUTEX_INITIALIZER; |
static fibril_mutex_t dev_lock; |
static int file_bd_init(const char *fname); |
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int file_bd_read(off_t blk_idx, off_t size, void *buf); |
static int file_bd_write(off_t blk_idx, off_t size, void *buf); |
static int file_bd_read(off_t blk_idx, size_t size, void *buf); |
static int file_bd_write(off_t blk_idx, size_t size, void *buf); |
int main(int argc, char **argv) |
{ |
86,6 → 87,7 |
} |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
106,6 → 108,8 |
if (img == NULL) |
return EINVAL; |
fibril_mutex_initialize(&dev_lock); |
return EOK; |
} |
118,7 → 122,7 |
int flags; |
int retval; |
off_t idx; |
off_t size; |
size_t size; |
/* Answer the IPC_M_CONNECT_ME_TO call. */ |
ipc_answer_0(iid, EOK); |
165,27 → 169,21 |
} |
} |
static int file_bd_read(off_t blk_idx, off_t size, void *buf) |
static int file_bd_read(off_t blk_idx, size_t size, void *buf) |
{ |
size_t n_rd; |
printf("file_bd_read\n"); |
futex_down(&dev_futex); |
fibril_mutex_lock(&dev_lock); |
printf("seek\n"); |
fseek(img, blk_idx * size, SEEK_SET); |
printf("read\n"); |
n_rd = fread(buf, 1, size, img); |
printf("done\n"); |
printf("done\n"); |
if (ferror(img)) { |
futex_up(&dev_futex); |
fibril_mutex_unlock(&dev_lock); |
return EIO; /* Read error */ |
} |
futex_up(&dev_futex); |
fibril_mutex_unlock(&dev_lock); |
if (n_rd < size) |
return EINVAL; /* Read beyond end of disk */ |
193,21 → 191,21 |
return EOK; |
} |
static int file_bd_write(off_t blk_idx, off_t size, void *buf) |
static int file_bd_write(off_t blk_idx, size_t size, void *buf) |
{ |
size_t n_wr; |
futex_down(&dev_futex); |
fibril_mutex_lock(&dev_lock); |
fseek(img, blk_idx * size, SEEK_SET); |
n_wr = fread(buf, 1, size, img); |
if (ferror(img) || n_wr < size) { |
futex_up(&dev_futex); |
fibril_mutex_unlock(&dev_lock); |
return EIO; /* Write error */ |
} |
futex_up(&dev_futex); |
fibril_mutex_unlock(&dev_lock); |
return EOK; |
} |
/branches/dd/uspace/srv/bd/rd/rd.c |
---|
50,7 → 50,7 |
#include <async.h> |
#include <align.h> |
#include <async.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <stdio.h> |
#include <devmap.h> |
#include <ipc/bd.h> |
63,12 → 63,12 |
static size_t rd_size; |
/** |
* This futex protects the ramdisk's data. |
* This rwlock 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. |
* protected by this rwlock. |
*/ |
atomic_t rd_futex = FUTEX_INITIALIZER; |
fibril_rwlock_t rd_lock; |
/** Handle one connection to ramdisk. |
* |
139,9 → 139,9 |
retval = ELIMIT; |
break; |
} |
futex_down(&rd_futex); |
fibril_rwlock_read_lock(&rd_lock); |
memcpy(fs_va, rd_addr + offset * block_size, block_size); |
futex_up(&rd_futex); |
fibril_rwlock_read_unlock(&rd_lock); |
retval = EOK; |
break; |
case BD_WRITE_BLOCK: |
161,9 → 161,9 |
retval = ELIMIT; |
break; |
} |
futex_up(&rd_futex); |
fibril_rwlock_write_lock(&rd_lock); |
memcpy(rd_addr + offset * block_size, fs_va, block_size); |
futex_down(&rd_futex); |
fibril_rwlock_write_unlock(&rd_lock); |
retval = EOK; |
break; |
default: |
216,6 → 216,8 |
printf(NAME ": Unable to register device\n"); |
return false; |
} |
fibril_rwlock_initialize(&rd_lock); |
return true; |
} |
/branches/dd/uspace/srv/bd/gxe_bd/gxe_bd.c |
---|
42,10 → 42,11 |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <task.h> |
#define NAME "gxe_bd" |
91,11 → 92,11 |
static dev_handle_t dev_handle[MAX_DISKS]; |
static atomic_t dev_futex = FUTEX_INITIALIZER; |
static fibril_mutex_t dev_lock[MAX_DISKS]; |
static int gxe_bd_init(void); |
static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size, |
void *buf); |
static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size, |
void *buf); |
110,6 → 111,7 |
return -1; |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
145,6 → 147,7 |
name); |
return rc; |
} |
fibril_mutex_initialize(&dev_lock[i]); |
} |
return EOK; |
160,7 → 163,7 |
int flags; |
int retval; |
off_t idx; |
off_t size; |
size_t size; |
int disk_id, i; |
/* Get the device handle. */ |
220,7 → 223,7 |
} |
} |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size, |
void *buf) |
{ |
int rc; |
256,7 → 259,7 |
size_t i; |
uint32_t w; |
futex_down(&dev_futex); |
fibril_mutex_lock(&dev_lock[disk_id]); |
pio_write_32(&dev->offset_lo, (uint32_t) offset); |
pio_write_32(&dev->offset_hi, offset >> 32); |
pio_write_32(&dev->disk_id, disk_id); |
264,6 → 267,7 |
status = pio_read_32(&dev->status); |
if (status == STATUS_FAILURE) { |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EIO; |
} |
271,7 → 275,7 |
((uint8_t *) buf)[i] = w = pio_read_8(&dev->buffer[i]); |
} |
futex_up(&dev_futex); |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EOK; |
} |
285,7 → 289,7 |
pio_write_8(&dev->buffer[i], ((const uint8_t *) buf)[i]); |
} |
futex_down(&dev_futex); |
fibril_mutex_lock(&dev_lock[disk_id]); |
pio_write_32(&dev->offset_lo, (uint32_t) offset); |
pio_write_32(&dev->offset_hi, offset >> 32); |
pio_write_32(&dev->disk_id, disk_id); |
293,10 → 297,11 |
status = pio_read_32(&dev->status); |
if (status == STATUS_FAILURE) { |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EIO; |
} |
futex_up(&dev_futex); |
fibril_mutex_unlock(&dev_lock[disk_id]); |
return EOK; |
} |
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.h |
---|
36,6 → 36,7 |
#define __ATA_BD_H__ |
#include <sys/types.h> |
#include <fibril_sync.h> |
enum { |
CTL_READ_START = 0, |
50,22 → 51,32 |
MAX_DISKS = 2 |
}; |
/** ATA Command Register Block. */ |
typedef union { |
/* Read */ |
/* Read/Write */ |
struct { |
uint8_t data_port; |
uint8_t error; |
uint16_t data_port; |
uint8_t sector_count; |
uint8_t sector_number; |
uint8_t cylinder_low; |
uint8_t cylinder_high; |
uint8_t drive_head; |
uint8_t pad_rw0; |
}; |
/* Read Only */ |
struct { |
uint8_t pad_ro0; |
uint8_t error; |
uint8_t pad_ro1[5]; |
uint8_t status; |
}; |
/* Write */ |
/* Write Only */ |
struct { |
uint8_t pad0[7]; |
uint8_t pad_wo0; |
uint8_t features; |
uint8_t pad_wo1[5]; |
uint8_t command; |
}; |
} ata_cmd_t; |
129,6 → 140,9 |
unsigned cylinders; |
unsigned sectors; |
uint64_t blocks; |
fibril_mutex_t lock; |
dev_handle_t dev_handle; |
} disk_t; |
#endif |
/branches/dd/uspace/srv/bd/ata_bd/ata_bd.c |
---|
37,6 → 37,9 |
* This driver currently works only with CHS addressing and uses PIO. |
* Currently based on the (now obsolete) ANSI X3.221-1994 (ATA-1) standard. |
* At this point only reading is possible, not writing. |
* |
* The driver services a single controller which can have up to two disks |
* attached. |
*/ |
#include <stdio.h> |
46,11 → 49,12 |
#include <ipc/bd.h> |
#include <async.h> |
#include <as.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <devmap.h> |
#include <sys/types.h> |
#include <errno.h> |
#include <bool.h> |
#include <task.h> |
#include "ata_bd.h" |
64,15 → 68,12 |
static ata_cmd_t *cmd; |
static ata_ctl_t *ctl; |
static dev_handle_t dev_handle[MAX_DISKS]; |
static atomic_t dev_futex = FUTEX_INITIALIZER; |
/** Per-disk state. */ |
static disk_t disk[MAX_DISKS]; |
static int ata_bd_init(void); |
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall); |
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size, |
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size, |
void *buf); |
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt, |
void *buf); |
89,14 → 90,15 |
printf(NAME ": ATA disk driver\n"); |
printf("cmd_physical = 0x%x\n", cmd_physical); |
printf("ctl_physical = 0x%x\n", ctl_physical); |
printf("I/O address 0x%x\n", cmd_physical); |
if (ata_bd_init() != EOK) |
return -1; |
/* Put drives to reset, disable interrupts. */ |
printf("Reset drives...\n"); |
printf("Reset drives... "); |
fflush(stdout); |
pio_write_8(&ctl->device_control, DCR_SRST); |
/* FIXME: Find out how to do this properly. */ |
async_usleep(100); |
107,8 → 109,6 |
} while ((status & SR_BSY) != 0); |
printf("Done\n"); |
printf("Status = 0x%x\n", pio_read_8(&cmd->status)); |
(void) drive_identify(0, &disk[0]); |
(void) drive_identify(1, &disk[1]); |
120,7 → 120,7 |
continue; |
snprintf(name, 16, "disk%d", i); |
rc = devmap_device_register(name, &dev_handle[i]); |
rc = devmap_device_register(name, &disk[i].dev_handle); |
if (rc != EOK) { |
devmap_hangup_phone(DEVMAP_DRIVER); |
printf(NAME ": Unable to register device %s.\n", |
136,6 → 136,7 |
} |
printf(NAME ": Accepting connections\n"); |
task_retval(0); |
async_manager(); |
/* Not reached */ |
146,15 → 147,16 |
{ |
uint16_t data; |
uint8_t status; |
int i; |
size_t i; |
printf("Identify drive %d\n", disk_id); |
printf("Identify drive %d... ", disk_id); |
fflush(stdout); |
pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0)); |
async_usleep(100); |
pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE); |
status = pio_read_8(&cmd->status); |
printf("Status = 0x%x\n", status); |
d->present = false; |
181,8 → 183,6 |
} |
} |
printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status)); |
d->blocks = d->cylinders * d->heads * d->sectors; |
printf("Geometry: %u cylinders, %u heads, %u sectors\n", |
189,6 → 189,7 |
d->cylinders, d->heads, d->sectors); |
d->present = true; |
fibril_mutex_initialize(&d->lock); |
return EOK; |
} |
234,7 → 235,7 |
int flags; |
int retval; |
off_t idx; |
off_t size; |
size_t size; |
int disk_id, i; |
/* Get the device handle. */ |
243,7 → 244,7 |
/* Determine which disk device is the client connecting to. */ |
disk_id = -1; |
for (i = 0; i < MAX_DISKS; i++) |
if (dev_handle[i] == dh) |
if (disk[i].dev_handle == dh) |
disk_id = i; |
if (disk_id < 0 || disk[disk_id].present == false) { |
294,14 → 295,14 |
} |
} |
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, off_t size, |
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size, |
void *buf) |
{ |
int rc; |
off_t now; |
size_t now; |
while (size > 0) { |
now = size < block_size ? size : (off_t) block_size; |
now = size < block_size ? size : block_size; |
if (now != block_size) |
return EINVAL; |
355,7 → 356,7 |
((disk_id != 0) ? DHR_DRV : 0) | |
(h & 0x0f); |
futex_down(&dev_futex); |
fibril_mutex_lock(&d->lock); |
/* Program a Read Sectors operation. */ |
377,7 → 378,7 |
((uint16_t *) buf)[i] = data; |
} |
futex_up(&dev_futex); |
fibril_mutex_unlock(&d->lock); |
return EOK; |
} |
409,7 → 410,7 |
((disk_id != 0) ? DHR_DRV : 0) | |
(h & 0x0f); |
futex_down(&dev_futex); |
fibril_mutex_lock(&d->lock); |
/* Program a Read Sectors operation. */ |
430,7 → 431,7 |
pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]); |
} |
futex_up(&dev_futex); |
fibril_mutex_unlock(&d->lock); |
return EOK; |
} |
/branches/dd/uspace/srv/loader/main.c |
---|
52,6 → 52,8 |
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <ipc/loader.h> |
#include <ipc/ns.h> |
#include <macros.h> |
#include <loader/pcb.h> |
#include <errno.h> |
#include <async.h> |
79,7 → 81,7 |
/** Number of preset files */ |
static int filc = 0; |
/** Preset files vector */ |
static char **filv = NULL; |
static fdi_node_t **filv = NULL; |
/** Buffer holding all preset files */ |
static fdi_node_t *fil_buf = NULL; |
437,16 → 439,24 |
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); |
/* Register at naming service. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0) |
return -1; |
return -2; |
async_manager(); |
/* Never reached */ |
/branches/dd/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, char *buf, size_t len) |
static int my_read(int fd, void *buf, size_t len) |
{ |
int cnt = 0; |
do { |
331,21 → 331,26 |
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) != |
(entry->p_vaddr % entry->p_align)) { |
(seg_addr % entry->p_align)) { |
DPRINTF("Align check 1 failed offset%%align=%d, " |
"vaddr%%align=%d\n", |
entry->p_offset % entry->p_align, |
entry->p_vaddr % entry->p_align |
seg_addr % entry->p_align |
); |
return EE_INVALID; |
} |
364,7 → 369,7 |
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE); |
mem_sz = entry->p_memsz + (entry->p_vaddr - base); |
DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias, |
DPRINTF("Map to seg_addr=0x%x-0x%x.\n", seg_addr, |
entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE)); |
/* |
379,7 → 384,7 |
} |
DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n", |
entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a); |
base + bias, mem_sz, flags, (uintptr_t)a); |
/* |
* Load segment data |
399,7 → 404,7 |
uint8_t *dp; |
left = entry->p_filesz; |
dp = (uint8_t *)(entry->p_vaddr + bias); |
dp = seg_ptr; |
while (left > 0) { |
now = 16384; |
416,7 → 421,7 |
dp += now; |
} |
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags); |
rc = as_area_change_flags(seg_ptr, flags); |
if (rc != 0) { |
DPRINTF("Failed to set memory area flags.\n"); |
return EE_MEMORY; |
424,7 → 429,7 |
if (flags & AS_AREA_EXEC) { |
/* Enforce SMC coherence for the segment */ |
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz)) |
if (smc_coherence(seg_ptr, entry->p_filesz)) |
return EE_MEMORY; |
} |
/branches/dd/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/dd/uspace/srv/fb/serial_console.c |
---|
388,6 → 388,10 |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, scr_width, scr_height); |
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; |
/branches/dd/uspace/srv/fb/fb.c |
---|
56,6 → 56,7 |
#include <async.h> |
#include <fibril.h> |
#include <bool.h> |
#include <stdio.h> |
#include "font-8x16.h" |
#include "fb.h" |
450,7 → 451,8 |
for (row = 0; row < vport->rows; row++) { |
x = vport->x; |
for (col = 0; col < vport->cols; col++) { |
if ((row + lines >= 0) && (row + lines < vport->rows)) { |
if (((int) row + lines >= 0) && |
((int) row + lines < (int) vport->rows)) { |
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)]; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
1066,10 → 1068,11 |
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)) |
shm = dest; |
else |
if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) { |
shm_id = 0; |
return false; |
} |
shm = dest; |
if (shm[0] != 'P') |
return false; |
1644,6 → 1647,9 |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, vport->cols, vport->rows); |
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))) { |
/branches/dd/uspace/srv/fb/ppm.c |
---|
89,7 → 89,7 |
{ |
unsigned int width, height; |
unsigned int maxcolor; |
int i; |
unsigned int i; |
unsigned int color; |
unsigned int coef; |
/branches/dd/uspace/srv/fb/ega.c |
---|
87,7 → 87,7 |
static void clrscr(void) |
{ |
int i; |
unsigned i; |
for (i = 0; i < scr_width * scr_height; i++) { |
scr_addr[i * 2] = ' '; |
129,7 → 129,8 |
static void scroll(int rows) |
{ |
int i; |
unsigned i; |
if (rows > 0) { |
memmove(scr_addr, ((char *) scr_addr) + rows * scr_width * 2, |
scr_width * scr_height * 2 - rows * scr_width * 2); |
318,6 → 319,9 |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, scr_width, scr_height); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, FB_CCAP_INDEXED); |
continue; |
case FB_CLEAR: |
clrscr(); |
retval = 0; |
345,7 → 349,7 |
break; |
case FB_SCROLL: |
i = IPC_GET_ARG1(call); |
if (i > scr_height || i < -((int) scr_height)) { |
if (i > (int) scr_height || i < -((int) scr_height)) { |
retval = EINVAL; |
break; |
} |
/branches/dd/uspace/srv/fs/devfs/devfs.c |
---|
65,37 → 65,39 |
ipc_callid_t callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_OUT_MOUNTED: |
devfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
devfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
devfs_lookup(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_OUT_OPEN_NODE: |
devfs_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
devfs_device(callid, &call); |
case VFS_OUT_STAT: |
devfs_stat(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
devfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
devfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
devfs_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_OUT_CLOSE: |
devfs_close(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
devfs_sync(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_DESTROY: |
devfs_destroy(callid, &call); |
break; |
default: |
/branches/dd/uspace/srv/fs/devfs/devfs_ops.c |
---|
41,7 → 41,9 |
#include <malloc.h> |
#include <string.h> |
#include <libfs.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <sys/stat.h> |
#include "devfs.h" |
#include "devfs_ops.h" |
58,6 → 60,9 |
/** Hash table of opened devices */ |
static hash_table_t devices; |
/** Hash table mutex */ |
static FIBRIL_MUTEX_INITIALIZE(devices_mutex); |
#define DEVICES_KEYS 1 |
#define DEVICES_KEY_HANDLE 0 |
#define DEVICES_BUCKETS 256 |
159,12 → 164,12 |
if (first >= last) { |
/* Root entry */ |
if (lflag & L_DIRECTORY) |
if (!(lflag & L_FILE)) |
ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0); |
else |
ipc_answer_0(rid, ENOENT); |
} else { |
if (lflag & L_FILE) { |
if (!(lflag & L_DIRECTORY)) { |
size_t len; |
if (last >= first) |
len = last - first + 1; |
195,10 → 200,12 |
[DEVICES_KEY_HANDLE] = (unsigned long) handle |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
int phone = devmap_device_connect(handle, 0); |
if (phone < 0) { |
fibril_mutex_unlock(&devices_mutex); |
free(name); |
ipc_answer_0(rid, ENOENT); |
return; |
206,6 → 213,7 |
device_t *dev = (device_t *) malloc(sizeof(device_t)); |
if (dev == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
free(name); |
ipc_answer_0(rid, ENOMEM); |
return; |
220,6 → 228,7 |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount++; |
} |
fibril_mutex_unlock(&devices_mutex); |
} |
free(name); |
238,10 → 247,12 |
[DEVICES_KEY_HANDLE] = (unsigned long) handle |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
int phone = devmap_device_connect(handle, 0); |
if (phone < 0) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
248,6 → 259,7 |
device_t *dev = (device_t *) malloc(sizeof(device_t)); |
if (dev == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
261,28 → 273,49 |
device_t *dev = hash_table_get_instance(lnk, device_t, link); |
dev->refcount++; |
} |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_3(rid, EOK, 0, 1, L_FILE); |
} |
void devfs_device(ipc_callid_t rid, ipc_call_t *request) |
void devfs_stat(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); |
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 = devfs_reg.fs_handle; |
stat.dev_handle = dev_handle; |
stat.index = index; |
stat.lnkcnt = 1; |
stat.is_file = (index != 0); |
stat.size = 0; |
if (index != 0) { |
unsigned long key[] = { |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
ipc_answer_1(rid, EOK, (ipcarg_t) index); |
} else |
ipc_answer_0(rid, ENOTSUP); |
if (lnk != NULL) |
stat.devfs_stat.device = (dev_handle_t)index; |
fibril_mutex_unlock(&devices_mutex); |
} |
ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); |
ipc_answer_0(rid, EOK); |
} |
void devfs_read(ipc_callid_t rid, ipc_call_t *request) |
295,8 → 328,10 |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
305,6 → 340,7 |
ipc_callid_t callid; |
if (!ipc_data_read_receive(&callid, NULL)) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
318,6 → 354,7 |
/* Forward the IPC_M_DATA_READ request to the driver */ |
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
fibril_mutex_unlock(&devices_mutex); |
/* Wait for reply from the driver. */ |
ipcarg_t rc; |
369,8 → 406,10 |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
379,6 → 418,7 |
ipc_callid_t callid; |
if (!ipc_data_write_receive(&callid, NULL)) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
393,6 → 433,8 |
/* Forward the IPC_M_DATA_WRITE request to the driver */ |
ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
fibril_mutex_unlock(&devices_mutex); |
/* Wait for reply from the driver. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
420,8 → 462,10 |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
434,6 → 478,8 |
hash_table_remove(&devices, key, DEVICES_KEYS); |
} |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, EOK); |
} else |
ipc_answer_0(rid, ENOTSUP); |
448,8 → 494,10 |
[DEVICES_KEY_HANDLE] = (unsigned long) index |
}; |
fibril_mutex_lock(&devices_mutex); |
link_t *lnk = hash_table_find(&devices, key); |
if (lnk == NULL) { |
fibril_mutex_unlock(&devices_mutex); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
461,6 → 509,8 |
aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request), |
IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer); |
fibril_mutex_unlock(&devices_mutex); |
/* Wait for reply from the driver */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
/branches/dd/uspace/srv/fs/devfs/devfs_ops.h |
---|
42,7 → 42,7 |
extern void devfs_mount(ipc_callid_t, ipc_call_t *); |
extern void devfs_lookup(ipc_callid_t, ipc_call_t *); |
extern void devfs_open_node(ipc_callid_t, ipc_call_t *); |
extern void devfs_device(ipc_callid_t, ipc_call_t *); |
extern void devfs_stat(ipc_callid_t, ipc_call_t *); |
extern void devfs_sync(ipc_callid_t, ipc_call_t *); |
extern void devfs_read(ipc_callid_t, ipc_call_t *); |
extern void devfs_write(ipc_callid_t, ipc_call_t *); |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.h |
---|
86,10 → 86,10 |
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_device(ipc_callid_t, ipc_call_t *); |
extern void tmpfs_sync(ipc_callid_t, ipc_call_t *); |
extern bool tmpfs_restore(dev_handle_t); |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs_dump.c |
---|
67,8 → 67,8 |
tmpfs_node_t *nodep; |
uint32_t size; |
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry), |
TMPFS_BLOCK_SIZE) != EOK) |
if (block_seqread(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_read(dev, bufpos, buflen, pos, fname, |
if (block_seqread(dev, bufpos, buflen, pos, fname, |
entry.len, TMPFS_BLOCK_SIZE) != EOK) { |
ops->destroy(fn); |
free(fname); |
103,7 → 103,7 |
} |
free(fname); |
if (block_read(dev, bufpos, buflen, pos, &size, |
if (block_seqread(dev, bufpos, buflen, pos, &size, |
sizeof(size), TMPFS_BLOCK_SIZE) != EOK) |
return false; |
115,7 → 115,7 |
return false; |
nodep->size = size; |
if (block_read(dev, bufpos, buflen, pos, nodep->data, |
if (block_seqread(dev, bufpos, buflen, pos, nodep->data, |
size, TMPFS_BLOCK_SIZE) != EOK) |
return false; |
131,7 → 131,7 |
return false; |
} |
if (block_read(dev, bufpos, buflen, pos, fname, |
if (block_seqread(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_read(dev, &bufpos, &buflen, &pos, tag, 5, |
if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5, |
TMPFS_BLOCK_SIZE) != EOK) |
goto error; |
/branches/dd/uspace/srv/fs/tmpfs/tmpfs.c |
---|
96,37 → 96,39 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_OUT_MOUNTED: |
tmpfs_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
tmpfs_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
tmpfs_lookup(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
tmpfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
tmpfs_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
tmpfs_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_OUT_CLOSE: |
tmpfs_close(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_DESTROY: |
tmpfs_destroy(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_OUT_OPEN_NODE: |
tmpfs_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
tmpfs_device(callid, &call); |
case VFS_OUT_STAT: |
tmpfs_stat(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
tmpfs_sync(callid, &call); |
break; |
default: |
150,7 → 152,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/dd/uspace/srv/fs/tmpfs/tmpfs_ops.c |
---|
628,9 → 628,9 |
libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_device(ipc_callid_t rid, ipc_call_t *request) |
void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request); |
} |
void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request) |
/branches/dd/uspace/srv/fs/fat/fat_idx.c |
---|
42,7 → 42,7 |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <fibril_sync.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; |
/** Futex protecting the list of unused structures. */ |
static futex_t unused_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the list of unused structures. */ |
static FIBRIL_MUTEX_INITIALIZE(unused_lock); |
/** List of unused structures. */ |
static LIST_INITIALIZE(unused_head); |
89,7 → 89,7 |
link_t *l; |
if (lock) |
futex_down(&unused_futex); |
fibril_mutex_lock(&unused_lock); |
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) |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return NULL; |
} |
/** Futex protecting the up_hash and ui_hash. */ |
static futex_t used_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the up_hash and ui_hash. */ |
static FIBRIL_MUTEX_INITIALIZE(used_lock); |
/** |
* Global hash table of all used fat_idx_t structures. |
231,7 → 231,7 |
*/ |
*index = u->next++; |
--u->remaining; |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return true; |
} |
} else { |
244,7 → 244,7 |
list_remove(&f->link); |
free(f); |
} |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return true; |
} |
/* |
252,7 → 252,7 |
* theoretically still possible (e.g. too many open unlinked nodes or |
* too many zero-sized nodes). |
*/ |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return false; |
} |
302,7 → 302,7 |
if (lnk->prev != &u->freed_head) |
try_coalesce_intervals(lnk->prev, lnk, |
lnk); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return; |
} |
if (f->last == index - 1) { |
310,7 → 310,7 |
if (lnk->next != &u->freed_head) |
try_coalesce_intervals(lnk, lnk->next, |
lnk); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return; |
} |
if (index > f->first) { |
321,7 → 321,7 |
n->first = index; |
n->last = index; |
list_insert_before(&n->link, lnk); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return; |
} |
335,7 → 335,7 |
n->last = index; |
list_append(&n->link, &u->freed_head); |
} |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
} |
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); |
futex_initialize(&fidx->lock, 1); |
fibril_mutex_initialize(&fidx->lock); |
fidx->dev_handle = dev_handle; |
fidx->pfc = FAT_CLST_RES0; /* no parent yet */ |
fidx->pdi = 0; |
365,10 → 365,10 |
{ |
fat_idx_t *fidx; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
fidx = fat_idx_create(dev_handle); |
if (!fidx) { |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
return NULL; |
} |
378,8 → 378,8 |
}; |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
futex_down(&fidx->lock); |
futex_up(&used_futex); |
fibril_mutex_lock(&fidx->lock); |
fibril_mutex_unlock(&used_lock); |
return fidx; |
} |
395,7 → 395,7 |
[UPH_PDI_KEY] = pdi, |
}; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
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) { |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
return NULL; |
} |
417,8 → 417,8 |
hash_table_insert(&up_hash, pkey, &fidx->uph_link); |
hash_table_insert(&ui_hash, ikey, &fidx->uih_link); |
} |
futex_down(&fidx->lock); |
futex_up(&used_futex); |
fibril_mutex_lock(&fidx->lock); |
fibril_mutex_unlock(&used_lock); |
return fidx; |
} |
431,9 → 431,9 |
[UPH_PDI_KEY] = idx->pdi, |
}; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
hash_table_insert(&up_hash, pkey, &idx->uph_link); |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
} |
void fat_idx_hashout(fat_idx_t *idx) |
444,9 → 444,9 |
[UPH_PDI_KEY] = idx->pdi, |
}; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
hash_table_remove(&up_hash, pkey, 3); |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
} |
fat_idx_t * |
459,13 → 459,13 |
[UIH_INDEX_KEY] = index, |
}; |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
l = hash_table_find(&ui_hash, ikey); |
if (l) { |
fidx = hash_table_get_instance(l, fat_idx_t, uih_link); |
futex_down(&fidx->lock); |
fibril_mutex_lock(&fidx->lock); |
} |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
return fidx; |
} |
483,7 → 483,7 |
assert(idx->pfc == FAT_CLST_RES0); |
futex_down(&used_futex); |
fibril_mutex_lock(&used_lock); |
/* |
* 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); |
futex_up(&used_futex); |
fibril_mutex_unlock(&used_lock); |
/* 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); |
futex_down(&unused_futex); |
fibril_mutex_lock(&unused_lock); |
if (!unused_find(dev_handle, false)) |
list_append(&u->link, &unused_head); |
else |
rc = EEXIST; |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
return rc; |
} |
540,7 → 540,7 |
u = unused_find(dev_handle, true); |
assert(u); |
list_remove(&u->link); |
futex_up(&unused_futex); |
fibril_mutex_unlock(&unused_lock); |
while (!list_empty(&u->freed_head)) { |
freed_t *f; |
/branches/dd/uspace/srv/fs/fat/fat.h |
---|
35,6 → 35,7 |
#include "fat_fat.h" |
#include <ipc/ipc.h> |
#include <fibril_sync.h> |
#include <libfs.h> |
#include <atomic.h> |
#include <sys/types.h> |
160,7 → 161,7 |
/** Used indices (index) hash table link. */ |
link_t uih_link; |
futex_t lock; |
fibril_mutex_t lock; |
dev_handle_t dev_handle; |
fs_index_t index; |
/** |
181,7 → 182,7 |
/** Back pointer to the FS node. */ |
fs_node_t *bp; |
futex_t lock; |
fibril_mutex_t lock; |
fat_node_type_t type; |
fat_idx_t *idx; |
/** |
206,10 → 207,11 |
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_device(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); |
/branches/dd/uspace/srv/fs/fat/fat_fat.c |
---|
45,15 → 45,15 |
#include <byteorder.h> |
#include <align.h> |
#include <assert.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <mem.h> |
/** |
* The fat_alloc_lock futex protects all copies of the File Allocation Table |
* The fat_alloc_lock mutex 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 futex_t fat_alloc_lock = FUTEX_INITIALIZER; |
static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); |
/** Walk the cluster chain. |
* |
326,7 → 326,7 |
/* |
* Search FAT1 for unused clusters. |
*/ |
futex_down(&fat_alloc_lock); |
fibril_mutex_lock(&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 → 350,7 |
*mcl = lifo[found - 1]; |
*lcl = lifo[0]; |
free(lifo); |
futex_up(&fat_alloc_lock); |
fibril_mutex_unlock(&fat_alloc_lock); |
return EOK; |
} |
} |
357,7 → 357,7 |
} |
block_put(blk); |
} |
futex_up(&fat_alloc_lock); |
fibril_mutex_unlock(&fat_alloc_lock); |
/* |
* We could not find enough clusters. Now we need to free the clusters |
/branches/dd/uspace/srv/fs/fat/fat.c |
---|
89,37 → 89,39 |
callid = async_get_call(&call); |
switch (IPC_GET_METHOD(call)) { |
case VFS_MOUNTED: |
case IPC_M_PHONE_HUNGUP: |
return; |
case VFS_OUT_MOUNTED: |
fat_mounted(callid, &call); |
break; |
case VFS_MOUNT: |
case VFS_OUT_MOUNT: |
fat_mount(callid, &call); |
break; |
case VFS_LOOKUP: |
case VFS_OUT_LOOKUP: |
fat_lookup(callid, &call); |
break; |
case VFS_READ: |
case VFS_OUT_READ: |
fat_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_OUT_WRITE: |
fat_write(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_OUT_TRUNCATE: |
fat_truncate(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_OUT_STAT: |
fat_stat(callid, &call); |
break; |
case VFS_OUT_CLOSE: |
fat_close(callid, &call); |
break; |
case VFS_DESTROY: |
case VFS_OUT_DESTROY: |
fat_destroy(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_OUT_OPEN_NODE: |
fat_open_node(callid, &call); |
break; |
case VFS_DEVICE: |
fat_device(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_OUT_SYNC: |
fat_sync(callid, &call); |
break; |
default: |
/branches/dd/uspace/srv/fs/fat/fat_ops.c |
---|
51,7 → 51,7 |
#include <adt/hash_table.h> |
#include <adt/list.h> |
#include <assert.h> |
#include <futex.h> |
#include <fibril_sync.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) |
/** Futex protecting the list of cached free FAT nodes. */ |
static futex_t ffn_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the list of cached free FAT nodes. */ |
static FIBRIL_MUTEX_INITIALIZE(ffn_mutex); |
/** List of cached free FAT nodes. */ |
static LIST_INITIALIZE(ffn_head); |
66,7 → 66,7 |
static void fat_node_initialize(fat_node_t *node) |
{ |
futex_initialize(&node->lock, 1); |
fibril_mutex_initialize(&node->lock); |
node->bp = NULL; |
node->idx = NULL; |
node->type = 0; |
115,30 → 115,30 |
fs_node_t *fn; |
fat_node_t *nodep; |
futex_down(&ffn_futex); |
fibril_mutex_lock(&ffn_mutex); |
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 (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK) |
if (!fibril_mutex_trylock(&nodep->lock)) |
goto skip_cache; |
idxp_tmp = nodep->idx; |
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) { |
futex_up(&nodep->lock); |
if (!fibril_mutex_trylock(&idxp_tmp->lock)) { |
fibril_mutex_unlock(&nodep->lock); |
goto skip_cache; |
} |
list_remove(&nodep->ffn_link); |
futex_up(&ffn_futex); |
fibril_mutex_unlock(&ffn_mutex); |
if (nodep->dirty) |
fat_node_sync(nodep); |
idxp_tmp->nodep = NULL; |
futex_up(&nodep->lock); |
futex_up(&idxp_tmp->lock); |
fibril_mutex_unlock(&nodep->lock); |
fibril_mutex_unlock(&idxp_tmp->lock); |
fn = FS_NODE(nodep); |
} else { |
skip_cache: |
/* Try to allocate a new node structure. */ |
futex_up(&ffn_futex); |
fibril_mutex_unlock(&ffn_mutex); |
fn = (fs_node_t *)malloc(sizeof(fs_node_t)); |
if (!fn) |
return NULL; |
175,10 → 175,10 |
* We are lucky. |
* The node is already instantiated in memory. |
*/ |
futex_down(&idxp->nodep->lock); |
fibril_mutex_lock(&idxp->nodep->lock); |
if (!idxp->nodep->refcnt++) |
list_remove(&idxp->nodep->ffn_link); |
futex_up(&idxp->nodep->lock); |
fibril_mutex_unlock(&idxp->nodep->lock); |
return idxp->nodep; |
} |
268,7 → 268,7 |
return NULL; |
/* idxp->lock held */ |
nodep = fat_node_get_core(idxp); |
futex_up(&idxp->lock); |
fibril_mutex_unlock(&idxp->lock); |
return FS_NODE(nodep); |
} |
277,12 → 277,12 |
fat_node_t *nodep = FAT_NODE(fn); |
bool destroy = false; |
futex_down(&nodep->lock); |
fibril_mutex_lock(&nodep->lock); |
if (!--nodep->refcnt) { |
if (nodep->idx) { |
futex_down(&ffn_futex); |
fibril_mutex_lock(&ffn_mutex); |
list_append(&nodep->ffn_link, &ffn_head); |
futex_up(&ffn_futex); |
fibril_mutex_unlock(&ffn_mutex); |
} else { |
/* |
* The node does not have any index structure associated |
293,7 → 293,7 |
destroy = true; |
} |
} |
futex_up(&nodep->lock); |
fibril_mutex_unlock(&nodep->lock); |
if (destroy) { |
free(nodep->bp); |
free(nodep); |
360,7 → 360,7 |
nodep->idx = idxp; |
idxp->nodep = nodep; |
futex_up(&idxp->lock); |
fibril_mutex_unlock(&idxp->lock); |
return FS_NODE(nodep); |
} |
409,16 → 409,16 |
fat_cluster_t mcl, lcl; |
int rc; |
futex_down(&childp->lock); |
fibril_mutex_lock(&childp->lock); |
if (childp->lnkcnt == 1) { |
/* |
* On FAT, we don't support multiple hard links. |
*/ |
futex_up(&childp->lock); |
fibril_mutex_unlock(&childp->lock); |
return EMLINK; |
} |
assert(childp->lnkcnt == 0); |
futex_up(&childp->lock); |
fibril_mutex_unlock(&childp->lock); |
if (!fat_dentry_name_verify(name)) { |
/* |
432,7 → 432,7 |
* a new one. |
*/ |
futex_down(&parentp->idx->lock); |
fibril_mutex_lock(&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 → 463,12 |
*/ |
if (parentp->idx->pfc == FAT_CLST_ROOT) { |
/* Can't grow the root directory. */ |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
return ENOSPC; |
} |
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); |
if (rc != EOK) { |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
return rc; |
} |
fat_append_clusters(bs, parentp, mcl); |
491,9 → 491,9 |
fat_dentry_name_set(d, name); |
b->dirty = true; /* need to sync block */ |
block_put(b); |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
futex_down(&childp->idx->lock); |
fibril_mutex_lock(&childp->idx->lock); |
/* |
* If possible, create the Sub-directory Identifier Entry and the |
529,12 → 529,12 |
childp->idx->pfc = parentp->firstc; |
childp->idx->pdi = i * dps + j; |
futex_up(&childp->idx->lock); |
fibril_mutex_unlock(&childp->idx->lock); |
futex_down(&childp->lock); |
fibril_mutex_lock(&childp->lock); |
childp->lnkcnt = 1; |
childp->dirty = true; /* need to sync node */ |
futex_up(&childp->lock); |
fibril_mutex_unlock(&childp->lock); |
/* |
* Hash in the index structure into the position hash. |
559,10 → 559,10 |
if (fat_has_children(cfn)) |
return ENOTEMPTY; |
futex_down(&parentp->lock); |
futex_down(&childp->lock); |
fibril_mutex_lock(&parentp->lock); |
fibril_mutex_lock(&childp->lock); |
assert(childp->lnkcnt == 1); |
futex_down(&childp->idx->lock); |
fibril_mutex_lock(&childp->idx->lock); |
bs = block_bb_get(childp->idx->dev_handle); |
bps = uint16_t_le2host(bs->bps); |
581,11 → 581,11 |
/* clear position information */ |
childp->idx->pfc = FAT_CLST_RES0; |
childp->idx->pdi = 0; |
futex_up(&childp->idx->lock); |
fibril_mutex_unlock(&childp->idx->lock); |
childp->lnkcnt = 0; |
childp->dirty = true; |
futex_up(&childp->lock); |
futex_up(&parentp->lock); |
fibril_mutex_unlock(&childp->lock); |
fibril_mutex_unlock(&parentp->lock); |
return EOK; |
} |
602,7 → 602,7 |
fat_dentry_t *d; |
block_t *b; |
futex_down(&parentp->idx->lock); |
fibril_mutex_lock(&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 → 617,7 |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
return NULL; |
default: |
case FAT_DENTRY_VALID: |
636,7 → 636,7 |
fat_idx_t *idx = fat_idx_get_by_pos( |
parentp->idx->dev_handle, parentp->firstc, |
i * dps + j); |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
if (!idx) { |
/* |
* Can happen if memory is low or if we |
646,7 → 646,7 |
return NULL; |
} |
nodep = fat_node_get_core(idx); |
futex_up(&idx->lock); |
fibril_mutex_unlock(&idx->lock); |
block_put(b); |
return FS_NODE(nodep); |
} |
654,7 → 654,7 |
block_put(b); |
} |
futex_up(&parentp->idx->lock); |
fibril_mutex_unlock(&parentp->idx->lock); |
return NULL; |
} |
686,7 → 686,7 |
if (nodep->type != FAT_DIRECTORY) |
return false; |
futex_down(&nodep->idx->lock); |
fibril_mutex_lock(&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 → 705,22 |
continue; |
case FAT_DENTRY_LAST: |
block_put(b); |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return false; |
default: |
case FAT_DENTRY_VALID: |
block_put(b); |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return true; |
} |
block_put(b); |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return true; |
} |
block_put(b); |
} |
futex_up(&nodep->idx->lock); |
fibril_mutex_unlock(&nodep->idx->lock); |
return false; |
} |
770,6 → 770,7 |
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; |
797,6 → 798,12 |
} |
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) { |
826,7 → 833,7 |
} |
/* Initialize the block cache */ |
rc = block_cache_init(dev_handle, bps, 0 /* XXX */); |
rc = block_cache_init(dev_handle, bps, 0 /* XXX */, cmode); |
if (rc != EOK) { |
block_fini(dev_handle); |
ipc_answer_0(rid, rc); |
881,7 → 888,7 |
rootp->bp = rfn; |
rfn->data = rootp; |
futex_up(&ridxp->lock); |
fibril_mutex_unlock(&ridxp->lock); |
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); |
} |
1195,9 → 1202,9 |
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_device(ipc_callid_t rid, ipc_call_t *request) |
void fat_stat(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_answer_0(rid, ENOTSUP); |
libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
} |
void fat_sync(ipc_callid_t rid, ipc_call_t *request) |
/branches/dd/uspace/srv/devmap/devmap.c |
---|
46,7 → 46,8 |
#include <string.h> |
#include <ipc/devmap.h> |
#define NAME "devmap" |
#define NAME "devmap" |
#define NULL_DEVICES 256 |
/** Representation of device driver. |
* |
83,16 → 84,8 |
devmap_driver_t *driver; |
} devmap_device_t; |
/** Pending lookup structure. */ |
typedef struct { |
link_t link; |
char *name; /**< Device name */ |
ipc_callid_t callid; /**< Call ID waiting for the lookup */ |
} pending_req_t; |
LIST_INITIALIZE(devices_list); |
LIST_INITIALIZE(drivers_list); |
LIST_INITIALIZE(pending_req); |
/* Locking order: |
* drivers_list_mutex |
102,10 → 95,13 |
**/ |
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 dev_handle_t last_handle = 0; |
static devmap_device_t *null_devices[NULL_DEVICES]; |
static dev_handle_t devmap_create_handle(void) |
{ |
174,10 → 170,8 |
} |
/** |
* |
* 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) |
{ |
191,10 → 185,8 |
} |
/** |
* |
* Read info about new driver and add it into linked list of registered |
* drivers. |
* |
*/ |
static void devmap_driver_register(devmap_driver_t **odriver) |
{ |
344,31 → 336,6 |
return EOK; |
} |
/** Process pending lookup requests */ |
static void process_pending_lookup(void) |
{ |
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 |
* |
*/ |
445,6 → 412,7 |
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); |
ipc_answer_1(iid, EOK, device->handle); |
530,10 → 498,14 |
} |
name[size] = '\0'; |
fibril_mutex_lock(&devices_list_mutex); |
const devmap_device_t *dev; |
recheck: |
/* |
* Find device name in linked list of known devices. |
* Find device name in the list of known devices. |
*/ |
const devmap_device_t *dev = devmap_device_find_name(name); |
dev = devmap_device_find_name(name); |
/* |
* Device was not found. |
540,24 → 512,18 |
*/ |
if (dev == NULL) { |
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) { |
/* 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; |
/* Blocking lookup */ |
fibril_condvar_wait(&devices_list_cv, |
&devices_list_mutex); |
goto recheck; |
} |
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); |
655,21 → 621,43 |
ipc_answer_1(iid, EOK, pos); |
} |
/** Initialize device mapper. |
* |
* |
*/ |
static bool devmap_init() |
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) |
return false; |
if (device == NULL) { |
fibril_mutex_unlock(&null_devices_mutex); |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
device->name = str_dup("null"); |
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); |
return false; |
ipc_answer_0(iid, ENOMEM); |
return; |
} |
list_initialize(&(device->devices)); |
681,11 → 669,50 |
device->handle = devmap_create_handle(); |
device->driver = NULL; |
/* Insert device into list of all devices */ |
/* 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; |
} |
738,7 → 765,7 |
} |
} |
if (NULL != driver) { |
if (driver != NULL) { |
/* |
* Unregister the device driver and all its devices. |
*/ |
770,6 → 797,12 |
case DEVMAP_DEVICE_GET_NAME: |
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; |
818,9 → 851,7 |
return -1; |
} |
/* Set a handler of incomming connections and |
pending operations */ |
async_set_pending(process_pending_lookup); |
/* Set a handler of incomming connections */ |
async_set_client_connection(devmap_connection); |
/* Register device mapper at naming service */ |
/branches/dd/uspace/srv/vfs/vfs.c |
---|
43,7 → 43,6 |
#include <bool.h> |
#include <string.h> |
#include <as.h> |
#include <adt/list.h> |
#include <atomic.h> |
#include "vfs.h" |
80,56 → 79,52 |
case IPC_M_PHONE_HUNGUP: |
keep_on_going = false; |
break; |
case VFS_REGISTER: |
case VFS_IN_REGISTER: |
vfs_register(callid, &call); |
/* |
* 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. |
*/ |
keep_on_going = false; |
break; |
case VFS_MOUNT: |
case VFS_IN_MOUNT: |
vfs_mount(callid, &call); |
break; |
case VFS_OPEN: |
case VFS_IN_OPEN: |
vfs_open(callid, &call); |
break; |
case VFS_OPEN_NODE: |
case VFS_IN_OPEN_NODE: |
vfs_open_node(callid, &call); |
break; |
case VFS_CLOSE: |
case VFS_IN_CLOSE: |
vfs_close(callid, &call); |
break; |
case VFS_READ: |
case VFS_IN_READ: |
vfs_read(callid, &call); |
break; |
case VFS_WRITE: |
case VFS_IN_WRITE: |
vfs_write(callid, &call); |
break; |
case VFS_SEEK: |
case VFS_IN_SEEK: |
vfs_seek(callid, &call); |
break; |
case VFS_TRUNCATE: |
case VFS_IN_TRUNCATE: |
vfs_truncate(callid, &call); |
break; |
case VFS_MKDIR: |
case VFS_IN_FSTAT: |
vfs_fstat(callid, &call); |
break; |
case VFS_IN_STAT: |
vfs_stat(callid, &call); |
break; |
case VFS_IN_MKDIR: |
vfs_mkdir(callid, &call); |
break; |
case VFS_UNLINK: |
case VFS_IN_UNLINK: |
vfs_unlink(callid, &call); |
break; |
case VFS_RENAME: |
case VFS_IN_RENAME: |
vfs_rename(callid, &call); |
break; |
case VFS_DEVICE: |
vfs_device(callid, &call); |
break; |
case VFS_SYNC: |
case VFS_IN_SYNC: |
vfs_sync(callid, &call); |
break; |
case VFS_NODE: |
vfs_node(callid, &call); |
break; |
default: |
ipc_answer_0(callid, ENOTSUP); |
break; |
144,11 → 139,6 |
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()) { |
159,7 → 149,6 |
/* |
* 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"); |
174,11 → 163,10 |
memset(plb, 0, PLB_SIZE); |
/* |
* Set a connectio handling function/fibril. |
* Set a connection handling function/fibril. |
*/ |
async_set_pending(vfs_process_pending_mount); |
async_set_client_connection(vfs_connection); |
/* |
* Register at the naming service. |
*/ |
/branches/dd/uspace/srv/vfs/vfs_ops.c |
---|
43,7 → 43,6 |
#include <stdlib.h> |
#include <string.h> |
#include <bool.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <unistd.h> |
55,20 → 54,6 |
/* 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; |
FIBRIL_MUTEX_INITIALIZE(pending_lock); |
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. |
123,7 → 108,7 |
/* |
* Now we hold a reference to mp_node. |
* It will be dropped upon the corresponding VFS_UNMOUNT. |
* It will be dropped upon the corresponding VFS_IN_UNMOUNT. |
* This prevents the mount point from being deleted. |
*/ |
} else { |
136,20 → 121,20 |
/* Tell the mountee that it is being mounted. */ |
phone = vfs_grab_phone(fs_handle); |
msg = async_send_1(phone, VFS_MOUNTED, |
msg = async_send_1(phone, VFS_OUT_MOUNTED, |
(ipcarg_t) dev_handle, &answer); |
/* send the mount options */ |
rc = ipc_data_write_start(phone, (void *)opts, |
str_size(opts)); |
if (rc != EOK) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
async_wait_for(msg, NULL); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
async_wait_for(msg, &rc); |
if (rc != EOK) { |
fibril_rwlock_write_unlock(&namespace_rwlock); |
196,10 → 181,9 |
int mountee_phone = vfs_grab_phone(fs_handle); |
assert(mountee_phone >= 0); |
vfs_release_phone(mountee_phone); |
phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
msg = async_send_4(phone, VFS_MOUNT, |
msg = async_send_4(phone, VFS_OUT_MOUNT, |
(ipcarg_t) mp_res.triplet.dev_handle, |
(ipcarg_t) mp_res.triplet.index, |
(ipcarg_t) fs_handle, |
208,8 → 192,9 |
/* 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); |
async_wait_for(msg, NULL); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
217,12 → 202,14 |
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) { |
async_wait_for(msg, NULL); |
vfs_release_phone(phone); |
async_wait_for(msg, NULL); |
/* Mount failed, drop reference to mp_node. */ |
if (mp_node) |
vfs_node_put(mp_node); |
230,8 → 217,8 |
ipc_answer_0(rid, rc); |
return; |
} |
async_wait_for(msg, &rc); |
vfs_release_phone(phone); |
async_wait_for(msg, &rc); |
if (rc == EOK) { |
rindex = (fs_index_t) IPC_GET_ARG1(answer); |
258,39 → 245,6 |
fibril_rwlock_write_unlock(&namespace_rwlock); |
} |
/** Process pending mount requests */ |
void vfs_process_pending_mount(void) |
{ |
link_t *cur; |
loop: |
fibril_mutex_lock(&pending_lock); |
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); |
fibril_mutex_unlock(&pending_lock); |
fibril_yield(); |
goto loop; |
} |
fibril_mutex_unlock(&pending_lock); |
} |
void vfs_mount(ipc_callid_t rid, ipc_call_t *request) |
{ |
/* |
444,35 → 398,17 |
* 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. |
*/ |
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
fibril_mutex_lock(&fs_head_lock); |
fs_handle_t fs_handle; |
recheck: |
fs_handle = fs_name_to_handle(fs_name, false); |
if (!fs_handle) { |
if (flags & IPC_FLAG_BLOCKING) { |
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); |
fibril_mutex_lock(&pending_lock); |
list_append(&pr->link, &pending_req); |
fibril_mutex_unlock(&pending_lock); |
return; |
fibril_condvar_wait(&fs_head_cv, &fs_head_lock); |
goto recheck; |
} |
fibril_mutex_unlock(&fs_head_lock); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
free(mp); |
480,6 → 416,7 |
free(opts); |
return; |
} |
fibril_mutex_unlock(&fs_head_lock); |
/* Acknowledge that we know fs_name. */ |
ipc_answer_0(callid, EOK); |
500,8 → 437,8 |
/* |
* The POSIX interface is open(path, oflag, mode). |
* We can receive oflags and mode along with the VFS_OPEN call; the path |
* will need to arrive in another call. |
* We can receive oflags and mode along with the VFS_IN_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(). |
618,7 → 555,7 |
* 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_CLOSE. |
* respective VFS_IN_CLOSE. |
*/ |
vfs_node_addref(node); |
vfs_node_put(node); |
695,7 → 632,7 |
* 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_CLOSE. |
* respective VFS_IN_CLOSE. |
*/ |
vfs_node_addref(node); |
vfs_node_put(node); |
704,7 → 641,7 |
ipc_answer_1(rid, EOK, fd); |
} |
void vfs_node(ipc_callid_t rid, ipc_call_t *request) |
void vfs_sync(ipc_callid_t rid, ipc_call_t *request) |
{ |
int fd = IPC_GET_ARG1(*request); |
715,21 → 652,6 |
return; |
} |
ipc_answer_3(rid, EOK, file->node->fs_handle, file->node->dev_handle, |
file->node->index); |
} |
void vfs_device(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. |
737,53 → 659,17 |
fibril_mutex_lock(&file->lock); |
int fs_phone = vfs_grab_phone(file->node->fs_handle); |
/* Make a VFS_DEVICE request at the destination FS server. */ |
/* Make a VFS_OUT_SYMC request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
file->node->dev_handle, file->node->index, &answer); |
vfs_release_phone(fs_phone); |
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); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer)); |
} |
void vfs_sync(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_SYMC request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
file->node->dev_handle, file->node->index, &answer); |
vfs_release_phone(fs_phone); |
/* Wait for reply from the FS server. */ |
ipcarg_t rc; |
async_wait_for(msg, &rc); |
fibril_mutex_unlock(&file->lock); |
ipc_answer_0(rid, rc); |
805,21 → 691,19 |
* 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_CLOSE request at the destination FS server. */ |
/* Make a VFS_OUT_CLOSE request at the destination FS server. */ |
aid_t msg; |
ipc_call_t answer; |
msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
file->node->dev_handle, file->node->index, &answer); |
msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle, |
file->node->index, &answer); |
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); |
fibril_mutex_unlock(&file->lock); |
int retval = IPC_GET_ARG1(answer); |
899,7 → 783,7 |
ipc_call_t answer; |
if (!read && file->append) |
file->pos = file->node->size; |
msg = async_send_3(fs_phone, IPC_GET_METHOD(*request), |
msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE, |
file->node->dev_handle, file->node->index, file->pos, &answer); |
/* |
910,12 → 794,12 |
*/ |
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) |
1013,7 → 897,7 |
int fs_phone; |
fs_phone = vfs_grab_phone(fs_handle); |
rc = async_req_3_0(fs_phone, VFS_TRUNCATE, (ipcarg_t)dev_handle, |
rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle, |
(ipcarg_t)index, (ipcarg_t)size); |
vfs_release_phone(fs_phone); |
return (int)rc; |
1043,6 → 927,106 |
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); |
1117,12 → 1101,12 |
/* |
* 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_DESTROY'ed after the last reference to it is dropped. |
* VFS_OUT_DESTROY'ed after the last reference to it is dropped. |
*/ |
vfs_node_t *node = vfs_node_get(&lr); |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
node->lnkcnt--; |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(node); |
ipc_answer_0(rid, EOK); |
1271,9 → 1255,9 |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
new_node->lnkcnt--; |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
break; |
default: |
fibril_rwlock_write_unlock(&namespace_rwlock); |
1293,9 → 1277,9 |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
old_node->lnkcnt++; |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
/* Destroy the link for the old name. */ |
rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); |
if (rc != EOK) { |
1308,9 → 1292,9 |
free(new); |
return; |
} |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
old_node->lnkcnt--; |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
fibril_rwlock_write_unlock(&namespace_rwlock); |
vfs_node_put(old_node); |
if (new_node) |
/branches/dd/uspace/srv/vfs/vfs_register.c |
---|
52,8 → 52,9 |
#include <atomic.h> |
#include "vfs.h" |
FIBRIL_CONDVAR_INITIALIZE(fs_head_cv); |
FIBRIL_MUTEX_INITIALIZE(fs_head_lock); |
link_t fs_head; |
LIST_INITIALIZE(fs_head); |
atomic_t fs_handle_next = { |
.count = 1 |
268,6 → 269,7 |
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); |
dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n", |
283,13 → 285,14 |
*/ |
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. 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(). |
* 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. |
*/ |
fibril_mutex_lock(&fs_head_lock); |
link_t *cur; |
299,7 → 302,11 |
if (fs->fs_handle == handle) { |
fibril_mutex_unlock(&fs_head_lock); |
fibril_mutex_lock(&fs->phone_lock); |
return fs->phone; |
phone = ipc_connect_me_to(fs->phone, 0, 0, 0); |
fibril_mutex_unlock(&fs->phone_lock); |
assert(phone > 0); |
return phone; |
} |
} |
fibril_mutex_unlock(&fs_head_lock); |
306,31 → 313,14 |
return 0; |
} |
/** Tell VFS that the phone is in use for any request. |
/** Tell VFS that the phone is not needed anymore. |
* |
* @param phone Phone to FS task. |
*/ |
void vfs_release_phone(int phone) |
{ |
bool found = false; |
fibril_mutex_lock(&fs_head_lock); |
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; |
fibril_mutex_unlock(&fs_head_lock); |
fibril_mutex_unlock(&fs->phone_lock); |
return; |
} |
} |
fibril_mutex_unlock(&fs_head_lock); |
/* |
* Not good to get here. |
*/ |
assert(found == true); |
/* TODO: implement connection caching */ |
ipc_hangup(phone); |
} |
/** Convert file system name to its handle. |
/branches/dd/uspace/srv/vfs/vfs.h |
---|
36,7 → 36,6 |
#include <ipc/ipc.h> |
#include <adt/list.h> |
#include <fibril_sync.h> |
#include <futex.h> |
#include <sys/types.h> |
#include <devmap.h> |
#include <bool.h> |
145,8 → 144,10 |
off_t pos; |
} vfs_file_t; |
extern futex_t nodes_futex; |
extern fibril_mutex_t nodes_mutex; |
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. */ |
158,7 → 159,7 |
size_t len; /**< Number of characters in this PLB entry. */ |
} plb_entry_t; |
extern futex_t plb_futex; /**< Futex protecting plb and plb_head. */ |
extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */ |
extern uint8_t *plb; /**< Path Lookup Buffer */ |
extern link_t plb_head; /**< List of active PLB entries. */ |
193,19 → 194,19 |
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_device(ipc_callid_t, ipc_call_t *); |
extern void vfs_sync(ipc_callid_t, ipc_call_t *); |
extern void vfs_node(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/dd/uspace/srv/vfs/vfs_node.c |
---|
38,7 → 38,6 |
#include "vfs.h" |
#include <stdlib.h> |
#include <string.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <adt/hash_table.h> |
#include <assert.h> |
45,8 → 44,8 |
#include <async.h> |
#include <errno.h> |
/** Futex protecting the VFS node hash table. */ |
futex_t nodes_futex = FUTEX_INITIALIZER; |
/** Mutex protecting the VFS node hash table. */ |
FIBRIL_MUTEX_INITIALIZE(nodes_mutex); |
#define NODES_BUCKETS_LOG 8 |
#define NODES_BUCKETS (1 << NODES_BUCKETS_LOG) |
89,9 → 88,9 |
*/ |
void vfs_node_addref(vfs_node_t *node) |
{ |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
_vfs_node_addref(node); |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
} |
/** Decrement reference count of a VFS node. |
105,7 → 104,7 |
bool free_vfs_node = false; |
bool free_fs_node = false; |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
if (node->refcnt-- == 1) { |
/* |
* We are dropping the last reference to this node. |
121,7 → 120,7 |
if (!node->lnkcnt) |
free_fs_node = true; |
} |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
if (free_fs_node) { |
/* |
130,7 → 129,7 |
*/ |
int phone = vfs_grab_phone(node->fs_handle); |
ipcarg_t rc; |
rc = async_req_2_0(phone, VFS_DESTROY, |
rc = async_req_2_0(phone, VFS_OUT_DESTROY, |
(ipcarg_t)node->dev_handle, (ipcarg_t)node->index); |
assert(rc == EOK); |
vfs_release_phone(phone); |
161,12 → 160,12 |
link_t *tmp; |
vfs_node_t *node; |
futex_down(&nodes_futex); |
fibril_mutex_lock(&nodes_mutex); |
tmp = hash_table_find(&nodes, key); |
if (!tmp) { |
node = (vfs_node_t *) malloc(sizeof(vfs_node_t)); |
if (!node) { |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
return NULL; |
} |
memset(node, 0, sizeof(vfs_node_t)); |
193,7 → 192,7 |
assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN); |
_vfs_node_addref(node); |
futex_up(&nodes_futex); |
fibril_mutex_unlock(&nodes_mutex); |
return node; |
} |
/branches/dd/uspace/srv/vfs/vfs_lookup.c |
---|
42,14 → 42,14 |
#include <string.h> |
#include <stdarg.h> |
#include <bool.h> |
#include <futex.h> |
#include <fibril_sync.h> |
#include <adt/list.h> |
#include <vfs/canonify.h> |
#define min(a, b) ((a) < (b) ? (a) : (b)) |
futex_t plb_futex = FUTEX_INITIALIZER; |
link_t plb_head; /**< PLB entry ring buffer. */ |
FIBRIL_MUTEX_INITIALIZE(plb_mutex); |
LIST_INITIALIZE(plb_head); /**< PLB entry ring buffer. */ |
uint8_t *plb = NULL; |
/** Perform a path lookup. |
92,7 → 92,7 |
va_end(ap); |
} |
futex_down(&plb_futex); |
fibril_mutex_lock(&plb_mutex); |
plb_entry_t entry; |
link_initialize(&entry.plb_link); |
119,7 → 119,7 |
/* |
* The buffer cannot absorb the path. |
*/ |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
return ELIMIT; |
} |
} else { |
127,7 → 127,7 |
/* |
* The buffer cannot absorb the path. |
*/ |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
return ELIMIT; |
} |
} |
146,7 → 146,7 |
*/ |
list_append(&entry.plb_link, &plb_head); |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
/* |
* Copy the path into PLB. |
159,16 → 159,16 |
ipc_call_t answer; |
int phone = vfs_grab_phone(root->fs_handle); |
aid_t req = async_send_5(phone, VFS_LOOKUP, (ipcarg_t) first, |
aid_t req = async_send_5(phone, VFS_OUT_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); |
futex_down(&plb_futex); |
fibril_mutex_lock(&plb_mutex); |
list_remove(&entry.plb_link); |
/* |
* Erasing the path from PLB will come handy for debugging purposes. |
175,7 → 175,7 |
*/ |
memset(&plb[first], 0, cnt1); |
memset(plb, 0, cnt2); |
futex_up(&plb_futex); |
fibril_mutex_unlock(&plb_mutex); |
if ((rc == EOK) && (result)) { |
result->triplet.fs_handle = (fs_handle_t) IPC_GET_ARG1(answer); |
204,14 → 204,14 |
int phone = vfs_grab_phone(result->triplet.fs_handle); |
ipc_call_t answer; |
aid_t req = async_send_2(phone, VFS_OPEN_NODE, |
aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE, |
(ipcarg_t) result->triplet.dev_handle, |
(ipcarg_t) result->triplet.index, &answer); |
vfs_release_phone(phone); |
ipcarg_t rc; |
async_wait_for(req, &rc); |
vfs_release_phone(phone); |
if (rc == EOK) { |
result->size = (size_t) IPC_GET_ARG1(answer); |
/branches/dd/uspace/srv/vfs/vfs_file.c |
---|
57,7 → 57,7 |
* 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 futex. |
* don't need to protect it by a mutex. |
*/ |
fibril_local vfs_file_t **files = NULL; |
/branches/dd/HelenOS.config |
---|
396,6 → 396,9 |
% 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) |
456,3 → 459,9 |
% External ramdisk |
! [PLATFORM=sparc64] CONFIG_RD_EXTERNAL (y/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/dd/defaults/sparc64/Makefile.config |
---|
54,3 → 54,9 |
# External ramdisk |
CONFIG_RD_EXTERNAL = y |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/dd/defaults/ia64/Makefile.config |
---|
42,3 → 42,9 |
# Output device class |
CONFIG_HID_OUT = generic |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/dd/defaults/arm32/Makefile.config |
---|
30,3 → 30,9 |
# What is your output device? |
CONFIG_HID_OUT = generic |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/dd/defaults/ppc32/Makefile.config |
---|
36,3 → 36,9 |
# Use Block Address Translation by the loader |
CONFIG_BAT = y |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/dd/defaults/amd64/Makefile.config |
---|
54,3 → 54,9 |
# Default framebuffer depth |
CONFIG_VESA_BPP = 16 |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/dd/defaults/mips32/Makefile.config |
---|
36,3 → 36,9 |
# Output device class |
CONFIG_HID_OUT = generic |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |
/branches/dd/defaults/ia32/Makefile.config |
---|
60,3 → 60,9 |
# Default framebuffer depth |
CONFIG_VESA_BPP = 16 |
# Load disk drivers on startup |
CONFIG_START_BD = n |
# Mount /data on startup |
CONFIG_MOUNT_DATA = n |