Changeset 76b5a95c in mainline for uspace/lib/c


Ignore:
Timestamp:
2011-03-23T20:53:30Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
71af5a4
Parents:
5716e9a (diff), ab10b842 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Location:
uspace/lib/c
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/Makefile

    r5716e9a r76b5a95c  
    9191        generic/loader.c \
    9292        generic/getopt.c \
    93         generic/adt/list.o \
    94         generic/adt/hash_table.o \
     93        generic/adt/list.c \
     94        generic/adt/hash_table.c \
    9595        generic/adt/dynamic_fifo.c \
    9696        generic/adt/measured_strings.c \
  • uspace/lib/c/arch/abs32le/_link.ld.in

    r5716e9a r76b5a95c  
    4444        } :data
    4545       
    46         . = ALIGN(0x1000);
    47        
    48         _heap = .;
    49        
    5046        /DISCARD/ : {
    5147                *(*);
  • uspace/lib/c/arch/amd64/_link.ld.in

    r5716e9a r76b5a95c  
    55        text PT_LOAD FLAGS(5);
    66        data PT_LOAD FLAGS(6);
     7        debug PT_NOTE;
    78}
    89
     
    1314                *(.init);
    1415        } :text
     16       
    1517        .text : {
    1618                *(.text);
    1719                *(.rodata*);
    1820        } :text
    19 
     21       
    2022        . = . + 0x1000;
    21 
     23       
    2224        .data : {
    2325                *(.data);
    2426        } :data
     27       
    2528        .tdata : {
    2629                _tdata_start = .;
     
    3134                _tbss_end = .;
    3235        } :data
     36       
    3337        _tls_alignment = ALIGNOF(.tdata);
     38       
    3439        .bss : {
    3540                *(COMMON);
    3641                *(.bss);
    3742        } :data
    38 
    39         . = ALIGN(0x1000);
    40         _heap = .;
     43       
     44#ifdef CONFIG_LINE_DEBUG
     45        .comment 0 : { *(.comment); } :debug
     46        .debug_abbrev 0 : { *(.debug_abbrev); } :debug
     47        .debug_aranges 0 : { *(.debug_aranges); } :debug
     48        .debug_info 0 : { *(.debug_info); } :debug
     49        .debug_line 0 : { *(.debug_line); } :debug
     50        .debug_loc 0 : { *(.debug_loc); } :debug
     51        .debug_pubnames 0 : { *(.debug_pubnames); } :debug
     52        .debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
     53        .debug_ranges 0 : { *(.debug_ranges); } :debug
     54        .debug_str 0 : { *(.debug_str); } :debug
     55#endif
    4156       
    4257        /DISCARD/ : {
    4358                *(*);
    4459        }
    45 
    4660}
  • uspace/lib/c/arch/arm32/_link.ld.in

    r5716e9a r76b5a95c  
    99SECTIONS {
    1010        . = 0x1000 + SIZEOF_HEADERS;
    11 
     11       
    1212        .init : {
    1313                *(.init);
    14         } : text
     14        } :text
     15       
    1516        .text : {
    1617                *(.text);
    17         *(.rodata*);
     18                *(.rodata*);
    1819        } :text
    19 
     20       
    2021        . = . + 0x1000;
    21 
     22       
    2223        .data : {
    2324                *(.opd);
     
    2526                *(.sdata);
    2627        } :data
     28       
    2729        .tdata : {
    2830                _tdata_start = .;
     
    3335                _tbss_end = .;
    3436        } :data
     37       
    3538        _tls_alignment = ALIGNOF(.tdata);
     39       
    3640        .bss : {
    3741                *(.sbss);
    3842                *(.scommon);
    39         *(COMMON);
    40         *(.bss);
     43                *(COMMON);
     44                *(.bss);
    4145        } :data
    42        
    43         . = ALIGN(0x1000);
    44         _heap = .;
    4546       
    4647        /DISCARD/ : {
    4748                *(*);
    4849        }
    49 
    5050}
  • uspace/lib/c/arch/ia32/_link.ld.in

    r5716e9a r76b5a95c  
    55        text PT_LOAD FLAGS(5);
    66        data PT_LOAD FLAGS(6);
     7        debug PT_NOTE;
    78}
    89
     
    4243        } :data
    4344       
    44         . = ALIGN(0x1000);
    45        
    46         _heap = .;
     45#ifdef CONFIG_LINE_DEBUG
     46        .comment 0 : { *(.comment); } :debug
     47        .debug_abbrev 0 : { *(.debug_abbrev); } :debug
     48        .debug_aranges 0 : { *(.debug_aranges); } :debug
     49        .debug_info 0 : { *(.debug_info); } :debug
     50        .debug_line 0 : { *(.debug_line); } :debug
     51        .debug_loc 0 : { *(.debug_loc); } :debug
     52        .debug_pubnames 0 : { *(.debug_pubnames); } :debug
     53        .debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
     54        .debug_ranges 0 : { *(.debug_ranges); } :debug
     55        .debug_str 0 : { *(.debug_str); } :debug
     56#endif
    4757       
    4858        /DISCARD/ : {
  • uspace/lib/c/arch/ia64/_link.ld.in

    r5716e9a r76b5a95c  
    99SECTIONS {
    1010        . = 0x4000 + SIZEOF_HEADERS;
    11 
     11       
    1212        .init : {
    1313                *(.init);
    14         } : text
     14        } :text
     15       
    1516        .text : {
    1617                *(.text);
    1718                *(.rodata*);
    1819        } :text
    19 
     20       
    2021        . = . + 0x4000;
    21 
     22       
    2223        .got : {
    2324                _gp = .;
    2425                *(.got*);
    25         } :data
     26        } :data
     27       
    2628        .data : {
    2729                *(.opd);
     
    2931                *(.sdata);
    3032        } :data
     33       
    3134        .tdata : {
    3235                _tdata_start = .;
     
    3740                _tbss_end = .;
    3841        } :data
     42       
    3943        _tls_alignment = ALIGNOF(.tdata);
     44       
    4045        .bss : {
    4146                *(.sbss);
     
    4449                *(.bss);
    4550        } :data
    46 
    47         . = ALIGN(0x4000);
    48         _heap = .;
    49  
     51       
    5052        /DISCARD/ : {
    5153                *(*);
    52         }
     54        }
    5355}
  • uspace/lib/c/arch/mips32/_link.ld.in

    r5716e9a r76b5a95c  
    1313                *(.init);
    1414        } :text
     15       
    1516        .text : {
    16                 *(.text);
     17                *(.text);
    1718                *(.rodata*);
    1819        } :text
    19 
     20       
    2021        . = . + 0x4000;
    21 
     22       
    2223        .data : {
    2324                *(.data);
    2425                *(.data.rel*);
    2526        } :data
    26 
     27       
    2728        .got : {
    2829                _gp = .;
    2930                *(.got);
    3031        } :data
    31 
     32       
    3233        .tdata : {
    3334                _tdata_start = .;
    3435                *(.tdata);
    3536                _tdata_end = .;
     37        } :data
     38       
     39        .tbss : {
    3640                _tbss_start = .;
    3741                *(.tbss);
    3842                _tbss_end = .;
    3943        } :data
    40         _tls_alignment = ALIGNOF(.tdata);
    41 
     44       
     45        _tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
     46       
    4247        .sbss : {
    4348                *(.scommon);
    4449                *(.sbss);
    45         }       
     50        }
     51       
    4652        .bss : {
    4753                *(.bss);
    4854                *(COMMON);
    4955        } :data
    50 
    51         . = ALIGN(0x4000);
    52         _heap = .;
    53 
     56       
    5457        /DISCARD/ : {
    5558                *(*);
  • uspace/lib/c/arch/mips32/src/entry.s

    r5716e9a r76b5a95c  
    2929.text
    3030.section .init, "ax"
     31
    3132.global __entry
    32 .global __entry_driver
     33
    3334.set noreorder
    3435.option pic2
     
    5758        nop
    5859.end
    59 
    60 # Alignment of output section data to 0x4000
    61 .section .data
    62 .align 14
  • uspace/lib/c/arch/ppc32/_link.ld.in

    r5716e9a r76b5a95c  
    99SECTIONS {
    1010        . = 0x1000 + SIZEOF_HEADERS;
    11 
     11       
    1212        .init : {
    1313                *(.init);
    1414        } :text
     15       
    1516        .text : {
    1617                *(.text);
    1718                *(.rodata*);
    1819        } :text
    19 
     20       
    2021        . = . + 0x1000;
    21 
     22       
    2223        .data : {
    2324                *(.data);
    2425                *(.sdata);
    2526        } :data
     27       
    2628        .tdata : {
    2729                _tdata_start = .;
     
    3234                _tbss_end = .;
    3335        } :data
     36       
    3437        _tls_alignment = ALIGNOF(.tdata);
     38       
    3539        .bss : {
    3640                *(.sbss);
     
    3842                *(.bss);
    3943        } :data
    40 
    41         . = ALIGN(0x1000);
    42         _heap = .;
    4344       
    4445        /DISCARD/ : {
    4546                *(*);
    4647        }
    47 
    4848}
  • uspace/lib/c/arch/sparc64/_link.ld.in

    r5716e9a r76b5a95c  
    99SECTIONS {
    1010        . = 0x4000 + SIZEOF_HEADERS;
    11 
     11       
    1212        .init : {
    1313                *(.init);
    1414        } :text
     15       
    1516        .text : {
    1617                *(.text);
    1718                *(.rodata*);
    1819        } :text
    19 
     20       
    2021        . = . + 0x4000;
    21 
     22       
    2223        .got : {
    2324                 _gp = .;
    2425                 *(.got*);
    2526        } :data
     27       
    2628        .data : {
    2729                *(.data);
    2830                *(.sdata);
    2931        } :data
     32       
    3033        .tdata : {
    3134                _tdata_start = .;
     
    3639                _tbss_end = .;
    3740        } :data
     41       
    3842        _tls_alignment = ALIGNOF(.tdata);
     43       
    3944        .bss : {
    4045                *(.sbss);
     
    4247                *(.bss);
    4348        } :data
    44 
    45         . = ALIGN(0x4000);
    46         _heap = .;
    4749       
    4850        /DISCARD/ : {
    4951                *(*);
    5052        }
    51 
    5253}
  • uspace/lib/c/generic/as.c

    r5716e9a r76b5a95c  
    4040#include <bitops.h>
    4141#include <malloc.h>
    42 
    43 /** Last position allocated by as_get_mappable_page */
    44 static uintptr_t last_allocated = 0;
     42#include "private/libc.h"
    4543
    4644/** Create address space area.
     
    103101}
    104102
    105 /** Return pointer to some unmapped area, where fits new as_area
     103/** Return pointer to unmapped address space area
    106104 *
    107105 * @param size Requested size of the allocation.
    108106 *
    109  * @return pointer to the beginning
     107 * @return Pointer to the beginning of unmapped address space area.
    110108 *
    111109 */
    112110void *as_get_mappable_page(size_t size)
    113111{
    114         if (size == 0)
    115                 return NULL;
    116        
    117         size_t sz = 1 << (fnzb(size - 1) + 1);
    118         if (last_allocated == 0)
    119                 last_allocated = get_max_heap_addr();
    120        
    121         /*
    122          * Make sure we allocate from naturally aligned address.
    123          */
    124         uintptr_t res = ALIGN_UP(last_allocated, sz);
    125         last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
    126        
    127         return ((void *) res);
     112        return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
     113            (sysarg_t) __entry, (sysarg_t) size);
    128114}
    129115
  • uspace/lib/c/generic/async.c

    r5716e9a r76b5a95c  
    430430       
    431431        fid_t fid = fibril_create(notification_fibril, msg);
     432        if (fid == 0) {
     433                free(msg);
     434                futex_up(&async_futex);
     435                return false;
     436        }
     437       
    432438        fibril_add_ready(fid);
    433439       
     
    681687        conn->wdata.fid = fibril_create(connection_fibril, conn);
    682688       
    683         if (!conn->wdata.fid) {
     689        if (conn->wdata.fid == 0) {
    684690                free(conn);
     691               
    685692                if (callid)
    686693                        ipc_answer_0(callid, ENOMEM);
     694               
    687695                return (uintptr_t) NULL;
    688696        }
     
    853861{
    854862        fid_t fid = fibril_create(async_manager_fibril, NULL);
    855         fibril_add_manager(fid);
     863        if (fid != 0)
     864                fibril_add_manager(fid);
    856865}
    857866
  • uspace/lib/c/generic/devman.c

    r5716e9a r76b5a95c  
    123123}
    124124
    125 static int devman_send_match_id(int phone, match_id_t *match_id) \
    126 {
    127         ipc_call_t answer;
    128         aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
    129         int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id));
     125static int devman_send_match_id(int phone, match_id_t *match_id)
     126{
     127        ipc_call_t answer;
     128
     129        aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
     130            &answer);
     131        int retval = async_data_write_start(phone, match_id->id,
     132            str_size(match_id->id));
     133
    130134        async_wait_for(req, NULL);
    131135        return retval;
     
    133137
    134138
    135 static int devman_send_match_ids(int phone, match_id_list_t *match_ids) 
     139static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
    136140{
    137141        link_t *link = match_ids->ids.next;
    138142        match_id_t *match_id = NULL;
    139143        int ret = EOK;
    140        
     144
    141145        while (link != &match_ids->ids) {
    142146                match_id = list_get_instance(link, match_id_t, link);
    143                 if (EOK != (ret = devman_send_match_id(phone, match_id)))
    144                 {
    145                         printf("Driver failed to send match id, error number = %d\n", ret);
    146                         return ret;                     
    147                 }
     147                ret = devman_send_match_id(phone, match_id);
     148                if (ret != EOK) {
     149                        printf("Driver failed to send match id, error %d\n",
     150                            ret);
     151                        return ret;
     152                }
     153
    148154                link = link->next;
    149155        }
    150         return ret;     
    151 }
    152 
    153 int devman_child_device_register(
    154         const char *name, match_id_list_t *match_ids, devman_handle_t parent_handle, devman_handle_t *handle)
    155 {               
     156
     157        return ret;
     158}
     159
     160/** Add function to a device.
     161 *
     162 * Request devman to add a new function to the specified device owned by
     163 * this driver task.
     164 *
     165 * @param name          Name of the new function
     166 * @param ftype         Function type, fun_inner or fun_exposed
     167 * @param match_ids     Match IDs (should be empty for fun_exposed)
     168 * @param devh          Devman handle of the device
     169 * @param funh          Place to store handle of the new function
     170 *
     171 * @return              EOK on success or negative error code.
     172 */
     173int devman_add_function(const char *name, fun_type_t ftype,
     174    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
     175{
    156176        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     177        int fun_handle;
    157178       
    158179        if (phone < 0)
     
    161182        async_serialize_start();
    162183       
    163         int match_count = list_count(&match_ids->ids); 
    164         ipc_call_t answer;
    165         aid_t req = async_send_2(phone, DEVMAN_ADD_CHILD_DEVICE, parent_handle, match_count, &answer);
     184        int match_count = list_count(&match_ids->ids);
     185        ipc_call_t answer;
     186
     187        aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
     188            devh, match_count, &answer);
    166189
    167190        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     
    178201        async_serialize_end();
    179202       
    180         if (retval != EOK) {
    181                 if (handle != NULL) {
    182                         *handle = -1;
    183                 }
    184                 return retval;
    185         }       
    186        
    187         if (handle != NULL)
    188                 *handle = (int) IPC_GET_ARG1(answer);   
    189                
    190         return retval;
    191 }
    192 
    193 int devman_add_device_to_class(devman_handle_t devman_handle, const char *class_name)
     203        if (retval == EOK)
     204                fun_handle = (int) IPC_GET_ARG1(answer);
     205        else
     206                fun_handle = -1;
     207       
     208        *funh = fun_handle;
     209
     210        return retval;
     211}
     212
     213int devman_add_device_to_class(devman_handle_t devman_handle,
     214    const char *class_name)
    194215{
    195216        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     
    200221        async_serialize_start();
    201222        ipc_call_t answer;
    202         aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, devman_handle, &answer);
    203        
    204         sysarg_t retval = async_data_write_start(phone, class_name, str_size(class_name));
     223        aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
     224            devman_handle, &answer);
     225       
     226        sysarg_t retval = async_data_write_start(phone, class_name,
     227            str_size(class_name));
    205228        if (retval != EOK) {
    206229                async_wait_for(req, NULL);
     
    212235        async_serialize_end();
    213236       
    214         return retval; 
     237        return retval;
    215238}
    216239
     
    265288}
    266289
    267 int devman_device_get_handle(const char *pathname, devman_handle_t *handle, unsigned int flags)
     290int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
     291    unsigned int flags)
    268292{
    269293        int phone = devman_get_phone(DEVMAN_CLIENT, flags);
     
    278302            &answer);
    279303       
    280         sysarg_t retval = async_data_write_start(phone, pathname, str_size(pathname));
     304        sysarg_t retval = async_data_write_start(phone, pathname,
     305            str_size(pathname));
    281306        if (retval != EOK) {
    282307                async_wait_for(req, NULL);
  • uspace/lib/c/generic/fibril.c

    r5716e9a r76b5a95c  
    115115        fibril->retval = 0;
    116116        fibril->flags = 0;
     117       
     118        fibril->waits_for = NULL;
    117119       
    118120        return fibril;
     
    276278        fibril->arg = arg;
    277279
    278         fibril->waits_for = NULL;
    279        
    280280        context_save(&fibril->ctx);
    281281        context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack,
  • uspace/lib/c/generic/loader.c

    r5716e9a r76b5a95c  
    160160        int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
    161161        if (rc != EOK) {
     162                free(pa);
    162163                async_wait_for(req, NULL);
    163164                return rc;
  • uspace/lib/c/generic/malloc.c

    r5716e9a r76b5a95c  
    4747#include "private/malloc.h"
    4848
    49 /* Magic used in heap headers. */
    50 #define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0101
    51 
    52 /* Magic used in heap footers. */
    53 #define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0202
    54 
    55 /** Allocation alignment (this also covers the alignment of fields
    56     in the heap header and footer) */
     49/** Magic used in heap headers. */
     50#define HEAP_BLOCK_HEAD_MAGIC  UINT32_C(0xBEEF0101)
     51
     52/** Magic used in heap footers. */
     53#define HEAP_BLOCK_FOOT_MAGIC  UINT32_C(0xBEEF0202)
     54
     55/** Magic used in heap descriptor. */
     56#define HEAP_AREA_MAGIC  UINT32_C(0xBEEFCAFE)
     57
     58/** Allocation alignment.
     59 *
     60 * This also covers the alignment of fields
     61 * in the heap header and footer.
     62 *
     63 */
    5764#define BASE_ALIGN  16
    5865
    59 /**
    60  * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
    61  */
    62 #define MAX_HEAP_SIZE  (sizeof(uintptr_t) << 28)
    63 
    64 /**
    65  *
    66  */
    67 #define STRUCT_OVERHEAD  (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
    68 
    69 /**
    70  * Calculate real size of a heap block (with header and footer)
     66/** Overhead of each heap block. */
     67#define STRUCT_OVERHEAD \
     68        (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
     69
     70/** Calculate real size of a heap block.
     71 *
     72 * Add header and footer size.
     73 *
    7174 */
    7275#define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
    7376
    74 /**
    75  * Calculate net size of a heap block (without header and footer)
     77/** Calculate net size of a heap block.
     78 *
     79 * Subtract header and footer size.
     80 *
    7681 */
    7782#define NET_SIZE(size)  ((size) - STRUCT_OVERHEAD)
     83
     84/** Get first block in heap area.
     85 *
     86 */
     87#define AREA_FIRST_BLOCK(area) \
     88        (ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN))
     89
     90/** Get footer in heap block.
     91 *
     92 */
     93#define BLOCK_FOOT(head) \
     94        ((heap_block_foot_t *) \
     95            (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t)))
     96
     97/** Heap area.
     98 *
     99 * The memory managed by the heap allocator is divided into
     100 * multiple discontinuous heaps. Each heap is represented
     101 * by a separate address space area which has this structure
     102 * at its very beginning.
     103 *
     104 */
     105typedef struct heap_area {
     106        /** Start of the heap area (including this structure)
     107         *
     108         * Aligned on page boundary.
     109         *
     110         */
     111        void *start;
     112       
     113        /** End of the heap area (aligned on page boundary) */
     114        void *end;
     115       
     116        /** Next heap area */
     117        struct heap_area *next;
     118       
     119        /** A magic value */
     120        uint32_t magic;
     121} heap_area_t;
    78122
    79123/** Header of a heap block
     
    87131        bool free;
    88132       
     133        /** Heap area this block belongs to */
     134        heap_area_t *area;
     135       
    89136        /* A magic value to detect overwrite of heap header */
    90137        uint32_t magic;
     
    102149} heap_block_foot_t;
    103150
    104 /** Linker heap symbol */
    105 extern char _heap;
     151/** First heap area */
     152static heap_area_t *first_heap_area = NULL;
     153
     154/** Last heap area */
     155static heap_area_t *last_heap_area = NULL;
     156
     157/** Next heap block to examine (next fit algorithm) */
     158static heap_block_head_t *next = NULL;
    106159
    107160/** Futex for thread-safe heap manipulation */
    108161static futex_t malloc_futex = FUTEX_INITIALIZER;
    109162
    110 /** Address of heap start */
    111 static void *heap_start = 0;
    112 
    113 /** Address of heap end */
    114 static void *heap_end = 0;
    115 
    116 /** Maximum heap size */
    117 static size_t max_heap_size = (size_t) -1;
    118 
    119 /** Current number of pages of heap area */
    120 static size_t heap_pages = 0;
    121 
    122163/** Initialize a heap block
    123164 *
    124  * Fills in the structures related to a heap block.
     165 * Fill in the structures related to a heap block.
    125166 * Should be called only inside the critical section.
    126167 *
     
    128169 * @param size Size of the block including the header and the footer.
    129170 * @param free Indication of a free block.
    130  *
    131  */
    132 static void block_init(void *addr, size_t size, bool free)
     171 * @param area Heap area the block belongs to.
     172 *
     173 */
     174static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
    133175{
    134176        /* Calculate the position of the header and the footer */
    135177        heap_block_head_t *head = (heap_block_head_t *) addr;
    136         heap_block_foot_t *foot =
    137             (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
    138178       
    139179        head->size = size;
    140180        head->free = free;
     181        head->area = area;
    141182        head->magic = HEAP_BLOCK_HEAD_MAGIC;
     183       
     184        heap_block_foot_t *foot = BLOCK_FOOT(head);
    142185       
    143186        foot->size = size;
     
    160203        assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
    161204       
    162         heap_block_foot_t *foot =
    163             (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
     205        heap_block_foot_t *foot = BLOCK_FOOT(head);
    164206       
    165207        assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
     
    167209}
    168210
    169 /** Increase the heap area size
    170  *
    171  * Should be called only inside the critical section.
    172  *
    173  * @param size Number of bytes to grow the heap by.
    174  *
    175  */
    176 static bool grow_heap(size_t size)
     211/** Check a heap area structure
     212 *
     213 * @param addr Address of the heap area.
     214 *
     215 */
     216static void area_check(void *addr)
     217{
     218        heap_area_t *area = (heap_area_t *) addr;
     219       
     220        assert(area->magic == HEAP_AREA_MAGIC);
     221        assert(area->start < area->end);
     222        assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
     223        assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
     224}
     225
     226/** Create new heap area
     227 *
     228 * @param start Preffered starting address of the new area.
     229 * @param size  Size of the area.
     230 *
     231 */
     232static bool area_create(size_t size)
     233{
     234        void *start = as_get_mappable_page(size);
     235        if (start == NULL)
     236                return false;
     237       
     238        /* Align the heap area on page boundary */
     239        void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE);
     240        size_t asize = ALIGN_UP(size, PAGE_SIZE);
     241       
     242        astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
     243        if (astart == (void *) -1)
     244                return false;
     245       
     246        heap_area_t *area = (heap_area_t *) astart;
     247       
     248        area->start = astart;
     249        area->end = (void *)
     250            ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN);
     251        area->next = NULL;
     252        area->magic = HEAP_AREA_MAGIC;
     253       
     254        void *block = (void *) AREA_FIRST_BLOCK(area);
     255        size_t bsize = (size_t) (area->end - block);
     256       
     257        block_init(block, bsize, true, area);
     258       
     259        if (last_heap_area == NULL) {
     260                first_heap_area = area;
     261                last_heap_area = area;
     262        } else {
     263                last_heap_area->next = area;
     264                last_heap_area = area;
     265        }
     266       
     267        return true;
     268}
     269
     270/** Try to enlarge a heap area
     271 *
     272 * @param area Heap area to grow.
     273 * @param size Gross size of item to allocate (bytes).
     274 *
     275 */
     276static bool area_grow(heap_area_t *area, size_t size)
    177277{
    178278        if (size == 0)
     279                return true;
     280       
     281        area_check(area);
     282       
     283        size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size,
     284            PAGE_SIZE);
     285       
     286        /* New heap area size */
     287        void *end = (void *)
     288            ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN);
     289       
     290        /* Check for overflow */
     291        if (end < area->start)
    179292                return false;
    180 
    181         if ((heap_start + size < heap_start) || (heap_end + size < heap_end))
     293       
     294        /* Resize the address space area */
     295        int ret = as_area_resize(area->start, asize, 0);
     296        if (ret != EOK)
    182297                return false;
    183298       
    184         size_t heap_size = (size_t) (heap_end - heap_start);
    185        
    186         if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
    187                 return false;
    188        
    189         size_t pages = (size - 1) / PAGE_SIZE + 1;
    190        
    191         if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
    192             == EOK) {
    193                 void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
    194                     (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
    195                 block_init(heap_end, end - heap_end, true);
    196                 heap_pages += pages;
    197                 heap_end = end;
     299        /* Add new free block */
     300        block_init(area->end, (size_t) (end - area->end), true, area);
     301       
     302        /* Update heap area parameters */
     303        area->end = end;
     304       
     305        return true;
     306}
     307
     308/** Try to enlarge any of the heap areas
     309 *
     310 * @param size Gross size of item to allocate (bytes).
     311 *
     312 */
     313static bool heap_grow(size_t size)
     314{
     315        if (size == 0)
    198316                return true;
    199         }
    200        
    201         return false;
    202 }
    203 
    204 /** Decrease the heap area
    205  *
    206  * Should be called only inside the critical section.
    207  *
    208  * @param size Number of bytes to shrink the heap by.
    209  *
    210  */
    211 static void shrink_heap(void)
    212 {
    213         // TODO
     317       
     318        /* First try to enlarge some existing area */
     319        heap_area_t *area;
     320        for (area = first_heap_area; area != NULL; area = area->next) {
     321                if (area_grow(area, size))
     322                        return true;
     323        }
     324       
     325        /* Eventually try to create a new area */
     326        return area_create(AREA_FIRST_BLOCK(size));
     327}
     328
     329/** Try to shrink heap space
     330 *
     331 * In all cases the next pointer is reset.
     332 *
     333 */
     334static void heap_shrink(void)
     335{
     336        next = NULL;
    214337}
    215338
     
    223346void __malloc_init(void)
    224347{
    225         if (!as_area_create((void *) &_heap, PAGE_SIZE,
    226             AS_AREA_WRITE | AS_AREA_READ))
     348        if (!area_create(PAGE_SIZE))
    227349                abort();
    228        
    229         heap_pages = 1;
    230         heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
    231         heap_end =
    232             (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
    233        
    234         /* Make the entire area one large block. */
    235         block_init(heap_start, heap_end - heap_start, true);
    236 }
    237 
    238 /** Get maximum heap address
    239  *
    240  */
    241 uintptr_t get_max_heap_addr(void)
    242 {
    243         futex_down(&malloc_futex);
    244        
    245         if (max_heap_size == (size_t) -1)
    246                 max_heap_size =
    247                     max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
    248        
    249         uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
    250        
    251         futex_up(&malloc_futex);
    252        
    253         return max_heap_addr;
    254350}
    255351
     
    273369                /* Block big enough -> split. */
    274370                void *next = ((void *) cur) + size;
    275                 block_init(next, cur->size - size, true);
    276                 block_init(cur, size, false);
     371                block_init(next, cur->size - size, true, cur->area);
     372                block_init(cur, size, false, cur->area);
    277373        } else {
    278374                /* Block too small -> use as is. */
     
    281377}
    282378
    283 /** Allocate a memory block
     379/** Allocate memory from heap area starting from given block
    284380 *
    285381 * Should be called only inside the critical section.
    286  *
    287  * @param size  The size of the block to allocate.
    288  * @param align Memory address alignment.
    289  *
    290  * @return the address of the block or NULL when not enough memory.
    291  *
    292  */
    293 static void *malloc_internal(const size_t size, const size_t align)
    294 {
    295         if (align == 0)
    296                 return NULL;
    297        
    298         size_t falign = lcm(align, BASE_ALIGN);
    299         size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
    300        
    301         bool grown = false;
    302         void *result;
    303        
    304 loop:
    305         result = NULL;
    306         heap_block_head_t *cur = (heap_block_head_t *) heap_start;
    307        
    308         while ((result == NULL) && ((void *) cur < heap_end)) {
     382 * As a side effect this function also sets the current
     383 * pointer on successful allocation.
     384 *
     385 * @param area        Heap area where to allocate from.
     386 * @param first_block Starting heap block.
     387 * @param final_block Heap block where to finish the search
     388 *                    (may be NULL).
     389 * @param real_size   Gross number of bytes to allocate.
     390 * @param falign      Physical alignment of the block.
     391 *
     392 * @return Address of the allocated block or NULL on not enough memory.
     393 *
     394 */
     395static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block,
     396    heap_block_head_t *final_block, size_t real_size, size_t falign)
     397{
     398        area_check((void *) area);
     399        assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area));
     400        assert((void *) first_block < area->end);
     401       
     402        heap_block_head_t *cur;
     403        for (cur = first_block; (void *) cur < area->end;
     404            cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
    309405                block_check(cur);
     406               
     407                /* Finish searching on the final block */
     408                if ((final_block != NULL) && (cur == final_block))
     409                        break;
    310410               
    311411                /* Try to find a block that is free and large enough. */
    312412                if ((cur->free) && (cur->size >= real_size)) {
    313                         /* We have found a suitable block.
    314                            Check for alignment properties. */
    315                         void *addr = ((void *) cur) + sizeof(heap_block_head_t);
    316                         void *aligned = (void *) ALIGN_UP(addr, falign);
     413                        /*
     414                         * We have found a suitable block.
     415                         * Check for alignment properties.
     416                         */
     417                        void *addr = (void *)
     418                            ((uintptr_t) cur + sizeof(heap_block_head_t));
     419                        void *aligned = (void *)
     420                            ALIGN_UP((uintptr_t) addr, falign);
    317421                       
    318422                        if (addr == aligned) {
    319423                                /* Exact block start including alignment. */
    320424                                split_mark(cur, real_size);
    321                                 result = addr;
     425                               
     426                                next = cur;
     427                                return addr;
    322428                        } else {
    323429                                /* Block start has to be aligned */
     
    325431                               
    326432                                if (cur->size >= real_size + excess) {
    327                                         /* The current block is large enough to fit
    328                                            data in including alignment */
    329                                         if ((void *) cur > heap_start) {
    330                                                 /* There is a block before the current block.
    331                                                    This previous block can be enlarged to compensate
    332                                                    for the alignment excess */
    333                                                 heap_block_foot_t *prev_foot =
    334                                                     ((void *) cur) - sizeof(heap_block_foot_t);
     433                                        /*
     434                                         * The current block is large enough to fit
     435                                         * data in (including alignment).
     436                                         */
     437                                        if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) {
     438                                                /*
     439                                                 * There is a block before the current block.
     440                                                 * This previous block can be enlarged to
     441                                                 * compensate for the alignment excess.
     442                                                 */
     443                                                heap_block_foot_t *prev_foot = (heap_block_foot_t *)
     444                                                    ((void *) cur - sizeof(heap_block_foot_t));
    335445                                               
    336                                                 heap_block_head_t *prev_head =
    337                                                     (heap_block_head_t *) (((void *) cur) - prev_foot->size);
     446                                                heap_block_head_t *prev_head = (heap_block_head_t *)
     447                                                    ((void *) cur - prev_foot->size);
    338448                                               
    339449                                                block_check(prev_head);
     
    342452                                                heap_block_head_t *next_head = ((void *) cur) + excess;
    343453                                               
    344                                                 if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
    345                                                         /* The previous block is not free and there is enough
    346                                                            space to fill in a new free block between the previous
    347                                                            and current block */
    348                                                         block_init(cur, excess, true);
     454                                                if ((!prev_head->free) &&
     455                                                    (excess >= STRUCT_OVERHEAD)) {
     456                                                        /*
     457                                                         * The previous block is not free and there
     458                                                         * is enough free space left to fill in
     459                                                         * a new free block between the previous
     460                                                         * and current block.
     461                                                         */
     462                                                        block_init(cur, excess, true, area);
    349463                                                } else {
    350                                                         /* The previous block is free (thus there is no need to
    351                                                            induce additional fragmentation to the heap) or the
    352                                                            excess is small, thus just enlarge the previous block */
    353                                                         block_init(prev_head, prev_head->size + excess, prev_head->free);
     464                                                        /*
     465                                                         * The previous block is free (thus there
     466                                                         * is no need to induce additional
     467                                                         * fragmentation to the heap) or the
     468                                                         * excess is small. Therefore just enlarge
     469                                                         * the previous block.
     470                                                         */
     471                                                        block_init(prev_head, prev_head->size + excess,
     472                                                            prev_head->free, area);
    354473                                                }
    355474                                               
    356                                                 block_init(next_head, reduced_size, true);
     475                                                block_init(next_head, reduced_size, true, area);
    357476                                                split_mark(next_head, real_size);
    358                                                 result = aligned;
    359                                                 cur = next_head;
     477                                               
     478                                                next = next_head;
     479                                                return aligned;
    360480                                        } else {
    361                                                 /* The current block is the first block on the heap.
    362                                                    We have to make sure that the alignment excess
    363                                                    is large enough to fit a new free block just
    364                                                    before the current block */
     481                                                /*
     482                                                 * The current block is the first block
     483                                                 * in the heap area. We have to make sure
     484                                                 * that the alignment excess is large enough
     485                                                 * to fit a new free block just before the
     486                                                 * current block.
     487                                                 */
    365488                                                while (excess < STRUCT_OVERHEAD) {
    366489                                                        aligned += falign;
     
    371494                                                if (cur->size >= real_size + excess) {
    372495                                                        size_t reduced_size = cur->size - excess;
    373                                                         cur = (heap_block_head_t *) (heap_start + excess);
     496                                                        cur = (heap_block_head_t *)
     497                                                            (AREA_FIRST_BLOCK(area) + excess);
    374498                                                       
    375                                                         block_init(heap_start, excess, true);
    376                                                         block_init(cur, reduced_size, true);
     499                                                        block_init((void *) AREA_FIRST_BLOCK(area), excess,
     500                                                            true, area);
     501                                                        block_init(cur, reduced_size, true, area);
    377502                                                        split_mark(cur, real_size);
    378                                                         result = aligned;
     503                                                       
     504                                                        next = cur;
     505                                                        return aligned;
    379506                                                }
    380507                                        }
     
    382509                        }
    383510                }
    384                
    385                 /* Advance to the next block. */
    386                 cur = (heap_block_head_t *) (((void *) cur) + cur->size);
    387         }
    388        
    389         if ((result == NULL) && (!grown)) {
    390                 if (grow_heap(real_size)) {
    391                         grown = true;
     511        }
     512       
     513        return NULL;
     514}
     515
     516/** Allocate a memory block
     517 *
     518 * Should be called only inside the critical section.
     519 *
     520 * @param size  The size of the block to allocate.
     521 * @param align Memory address alignment.
     522 *
     523 * @return Address of the allocated block or NULL on not enough memory.
     524 *
     525 */
     526static void *malloc_internal(const size_t size, const size_t align)
     527{
     528        assert(first_heap_area != NULL);
     529       
     530        if (align == 0)
     531                return NULL;
     532       
     533        size_t falign = lcm(align, BASE_ALIGN);
     534        size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
     535       
     536        bool retry = false;
     537        heap_block_head_t *split;
     538       
     539loop:
     540       
     541        /* Try the next fit approach */
     542        split = next;
     543       
     544        if (split != NULL) {
     545                void *addr = malloc_area(split->area, split, NULL, real_size,
     546                    falign);
     547               
     548                if (addr != NULL)
     549                        return addr;
     550        }
     551       
     552        /* Search the entire heap */
     553        heap_area_t *area;
     554        for (area = first_heap_area; area != NULL; area = area->next) {
     555                heap_block_head_t *first = (heap_block_head_t *)
     556                    AREA_FIRST_BLOCK(area);
     557               
     558                void *addr = malloc_area(area, first, split, real_size,
     559                    falign);
     560               
     561                if (addr != NULL)
     562                        return addr;
     563        }
     564       
     565        if (!retry) {
     566                /* Try to grow the heap space */
     567                if (heap_grow(real_size)) {
     568                        retry = true;
    392569                        goto loop;
    393570                }
    394571        }
    395572       
    396         return result;
     573        return NULL;
    397574}
    398575
     
    473650            (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    474651       
    475         assert((void *) head >= heap_start);
    476         assert((void *) head < heap_end);
    477        
    478652        block_check(head);
    479653        assert(!head->free);
     654       
     655        heap_area_t *area = head->area;
     656       
     657        area_check(area);
     658        assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
     659        assert((void *) head < area->end);
    480660       
    481661        void *ptr = NULL;
     
    487667                /* Shrink */
    488668                if (orig_size - real_size >= STRUCT_OVERHEAD) {
    489                         /* Split the original block to a full block
    490                            and a trailing free block */
    491                         block_init((void *) head, real_size, false);
     669                        /*
     670                         * Split the original block to a full block
     671                         * and a trailing free block.
     672                         */
     673                        block_init((void *) head, real_size, false, area);
    492674                        block_init((void *) head + real_size,
    493                             orig_size - real_size, true);
    494                         shrink_heap();
     675                            orig_size - real_size, true, area);
     676                        heap_shrink();
    495677                }
    496678               
    497679                ptr = ((void *) head) + sizeof(heap_block_head_t);
    498680        } else {
    499                 /* Look at the next block. If it is free and the size is
    500                    sufficient then merge the two. Otherwise just allocate
    501                    a new block, copy the original data into it and
    502                    free the original block. */
     681                /*
     682                 * Look at the next block. If it is free and the size is
     683                 * sufficient then merge the two. Otherwise just allocate
     684                 * a new block, copy the original data into it and
     685                 * free the original block.
     686                 */
    503687                heap_block_head_t *next_head =
    504688                    (heap_block_head_t *) (((void *) head) + head->size);
    505689               
    506                 if (((void *) next_head < heap_end) &&
     690                if (((void *) next_head < area->end) &&
    507691                    (head->size + next_head->size >= real_size) &&
    508692                    (next_head->free)) {
    509693                        block_check(next_head);
    510                         block_init(head, head->size + next_head->size, false);
     694                        block_init(head, head->size + next_head->size, false, area);
    511695                        split_mark(head, real_size);
    512696                       
    513697                        ptr = ((void *) head) + sizeof(heap_block_head_t);
     698                        next = NULL;
    514699                } else
    515700                        reloc = true;
     
    542727            = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    543728       
    544         assert((void *) head >= heap_start);
    545         assert((void *) head < heap_end);
    546        
    547729        block_check(head);
    548730        assert(!head->free);
     731       
     732        heap_area_t *area = head->area;
     733       
     734        area_check(area);
     735        assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
     736        assert((void *) head < area->end);
    549737       
    550738        /* Mark the block itself as free. */
     
    555743            = (heap_block_head_t *) (((void *) head) + head->size);
    556744       
    557         if ((void *) next_head < heap_end) {
     745        if ((void *) next_head < area->end) {
    558746                block_check(next_head);
    559747                if (next_head->free)
    560                         block_init(head, head->size + next_head->size, true);
     748                        block_init(head, head->size + next_head->size, true, area);
    561749        }
    562750       
    563751        /* Look at the previous block. If it is free, merge the two. */
    564         if ((void *) head > heap_start) {
     752        if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
    565753                heap_block_foot_t *prev_foot =
    566754                    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
     
    572760               
    573761                if (prev_head->free)
    574                         block_init(prev_head, prev_head->size + head->size, true);
    575         }
    576        
    577         shrink_heap();
     762                        block_init(prev_head, prev_head->size + head->size, true,
     763                            area);
     764        }
     765       
     766        heap_shrink();
    578767       
    579768        futex_up(&malloc_futex);
  • uspace/lib/c/generic/private/libc.h

    r5716e9a r76b5a95c  
    3636#define LIBC_PRIVATE_LIBC_H_
    3737
     38extern void __entry(void);
     39extern void __main(void *) __attribute__((noreturn));
    3840extern int main(int, char *[]);
    39 extern void __main(void *) __attribute__((noreturn));
    4041
    4142#endif
  • uspace/lib/c/include/as.h

    r5716e9a r76b5a95c  
    4141#include <libarch/config.h>
    4242
     43static inline size_t SIZE2PAGES(size_t size)
     44{
     45        if (size == 0)
     46                return 0;
     47       
     48        return (size_t) ((size - 1) >> PAGE_WIDTH) + 1;
     49}
     50
     51static inline size_t PAGES2SIZE(size_t pages)
     52{
     53        return (size_t) (pages << PAGE_WIDTH);
     54}
     55
    4356extern void *as_area_create(void *address, size_t size, int flags);
    4457extern int as_area_resize(void *address, size_t size, int flags);
  • uspace/lib/c/include/devman.h

    r5716e9a r76b5a95c  
    4545
    4646extern int devman_driver_register(const char *, async_client_conn_t);
    47 extern int devman_child_device_register(const char *, match_id_list_t *,
     47extern int devman_add_function(const char *, fun_type_t, match_id_list_t *,
    4848    devman_handle_t, devman_handle_t *);
    4949
  • uspace/lib/c/include/ipc/devman.h

    r5716e9a r76b5a95c  
    4242
    4343typedef sysarg_t devman_handle_t;
     44
     45typedef enum {
     46        /** Invalid value for debugging purposes */
     47        fun_invalid = 0,
     48        /** Function to which child devices attach */
     49        fun_inner,
     50        /** Fuction exported to external clients (leaf function) */
     51        fun_exposed
     52} fun_type_t;
    4453
    4554/** Ids of device models used for device-to-driver matching.
     
    127136typedef enum {
    128137        DEVMAN_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
    129         DEVMAN_ADD_CHILD_DEVICE,
     138        DEVMAN_ADD_FUNCTION,
    130139        DEVMAN_ADD_MATCH_ID,
    131140        DEVMAN_ADD_DEVICE_TO_CLASS
  • uspace/lib/c/include/malloc.h

    r5716e9a r76b5a95c  
    3838#include <sys/types.h>
    3939
    40 extern uintptr_t get_max_heap_addr(void);
    41 
    4240extern void *malloc(const size_t size)
    4341    __attribute__((malloc));
  • uspace/lib/c/include/unistd.h

    r5716e9a r76b5a95c  
    4444#endif
    4545
    46 #define getpagesize()  (PAGE_SIZE)
    47 
    4846#ifndef SEEK_SET
    4947        #define SEEK_SET  0
     
    5755        #define SEEK_END  2
    5856#endif
     57
     58#define getpagesize()  (PAGE_SIZE)
    5959
    6060extern int dup2(int oldfd, int newfd);
Note: See TracChangeset for help on using the changeset viewer.